本題是浙江理工大學ACM入隊200題第八套中的E題
我們先來看一下這題的題面.
題面
輸入
輸入資料包含多個測驗實體,每個測驗實體占一行,每行的第一個數為n,表示本組資料一共有n個,接著是n個整數,你可以假設每組資料必定至少存在一個奇數,
輸出
輸出每組數中的所有奇數的乘積,對于測驗實體,輸出一行,
樣例輸入
3 1 2 3
4 2 3 4 5
樣例輸出
3
15
題目分析
這題的思路非常簡單,只要遍歷一遍各個輸入,判斷奇數然后乘起來就好了(注意記錄結果的變數不要初始化為0,那樣無論你怎么乘結果還是0).
常見錯誤思路
但是,這題有一個非常容易錯的小細節,在ACM群里詢問的頻率也非常高,大部分詢問的朋友給出的判斷奇數的區域代碼都是如下這樣的:
if (a % 2 == 1)
{
res *= a;
}
常見錯誤原因決議
很多朋友都很納悶,對二取余為1,為啥就不是奇數了呢?
這是因為你不懂取模運算子的心.自C99起規定,如果取模操作左邊的運算元是正數,則取模的結果為正數(或零),但如果取模操作左邊的運算元是負數,則模除的結果為負數(或零).如果此題的資料中有負奇數,那么a % 2的計算結果是-1而不是1,所以這種判斷方式是不對的!
解決方案
那如何解決呢?最直接的辦法是使用或運算子連著-1一起判斷,區域代碼如下:
if (a % 2 == 1 || a % 2 == -1)
{
res *= a;
}
但這樣其實略顯麻煩,我們可以反著來,通過判斷這個數不是偶數來判斷奇數,反正在整型里沒有-0,不會出現問題(浮點數里有奧),區域代碼如下:
if (a % 2 == 0) // 不是偶數,就是奇數,反正偶數對2取模時無論整數結果都是0
{
res *= a;
}
當然,還有更簡單的寫法,這種寫法基于C弱型別的特性,我個人喜歡這種寫法.
我們知道,在C語言中是會進行很多自動型別轉換的.或者換一步說,在C中是沒有所謂布爾型(邏輯型)的(C++中有),而是用非零的數或者可以轉換為非0的數的東西表示true,而用零或者可以轉換為0的東西表示false.
對于奇偶數判斷,我們其實正是在對取模結果是零還是非零進行判斷,所以我們可以直接把取模操作作為if的條件運算式,代碼模板如下:
// 判斷奇數
if(a % 2) // 即a % 2的結果非零,也即奇數.
{
// 此處填寫具體處理代碼
}
// 判斷偶數
if(!a % 2) // 即a % 2的結果為零(非零不成立),也即偶數
{
// 此處填寫具體處理代碼
}
參考代碼
下面給出了我自己做這道題時候的完整代碼:
(僅作為參考,一定要自己寫一下奧,作弊沒意思,害人又害己)
#include <stdio.h>
int main()
{
int n;
while (~scanf("%d", &n)) // 處理多組輸入,如果你不熟悉位運算那就寫成scanf("%d", &n) != EOF
{
int res = 1; // 注意不要初始化成0
for (int i = 0; i < n; i++)
{
int num;
scanf("%d", &num);
if (num % 2) // num % 2的結果非零,也即奇數.
{
res *= num;
}
}
printf("%d\n", res);
}
return 0;
}
"正是我們每天反復做的事情,最終造就了我們,優秀不是一種行為,而是一種習慣" ---亞里士多德
這篇題解就到這里了,各位朋友如果有問題歡迎到acm成員群中提問哦!
這里是浙江理工大學22屆ACM集訓隊的成員一枚鴨!
本文首發于博客園,作者:星雙子,除了我自己的轉載請注明原文鏈接:https://www.cnblogs.com/gemini-star/p/zstuACM200_8E.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/509514.html
標籤:其他
下一篇:尼翠德Java初面
