「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积

本题是浙江理工大学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的结果为零(非零不成立),也即偶数,注意优先级
    {
        // 此处填写具体处理代码
    }

当然咯,如果你对位运算有所了解,这里还可以直接借助位运算来解决.如果你不知道什么是位运算并无关系,只要会写上面的代码就好了.位运算判断奇偶的代码模板如下:

    // 判断奇数
    if(a & 1) // 通过&1取出二进制最低位,奇数的二进制最低位一定为1(包括负数,证明略)
    {
        // 此处填写具体处理代码
    }

    // 判断偶数
    if(!(a & 1)) // 通过&1取出二进制最低位,偶数的二进制最低位一定为0(包括负数,证明略),注意优先级
    {
        // 此处填写具体处理代码
    }

参考代码

下面给出了我自己做这道题时候的完整代码:

(仅作为参考,一定要自己写一下奥,作弊没意思,害人又害己)

#include

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成员群中提问哦!

Original: https://www.cnblogs.com/gemini-star/p/zstuACM200_8E.html
Author: 星双子
Title: 「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/604082/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球