基础逻辑-分类讨论

比赛:SDKD 2020 Autumn Training Series C2 1st Round

题目出处:cf #646 CodeForces - 1363A

题目大意:

给定n个数字,然后从中选择x个数字,使得x个数字的和为奇数。询问该种情况是否可能

解析:

1、我的思路:

由于:奇数+奇数=偶数,奇数+偶数=奇数,偶数+偶数=偶数,那么我们可以知道,x个数字如果能够和为奇数,那么在x数字中一定有奇数个奇数以及不知道多少个偶数。

根据上述的思路,我们枚举所有可能的奇数的个数,然后通过x得到需要的偶数的个数。之后根据已有偶数个数是否能够满足所需偶数个数来确定结果。

当然,这里仍然需要注意一个要点。由于奇数+奇数=偶数(即偶数个奇数和为偶数),那么是否可能存在:某一次枚举过程中,由于偶数个数不能满足,需要使用成对的奇数来代替偶数的情况呢?

我们假设这种情况是存在的,那么我们所需要的用来替代偶数的成对奇数,一定是有偶数个奇数的。因为只有偶数个奇数才能充当偶数来使用。这时,我们发现,最终结果仍然是由奇数个奇数组成的。

所以上述的额外情况并不需要特殊处理,它已经被包含到了遍历的过程中。

代码如下:

const int maxn = 1000+100;
int a[maxn];
int main(){
    //freopen("in.txt","r",stdin);
    int num;
    cin>>num;
    while(num--){
        int n,x;
        scanf("%d%d",&n,&x);
        int odd  = 0;
        int even = 0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            if(a[i]&1)odd++;
            else even++;
        }
        //开始处理一般情况
        bool ok = false;
        int odd_num = 1;
        while(odd_num<=odd && odd_num<=x){
            //这里的一个坑就是odd的选用个数不仅不能超过odd总个数
            //也不能超过所要求选取的总个数
            if(x - odd_num <= even){
                ok=true;break;
            }
            odd_num+=2;
        }
        if(ok){
            cout<<"Yes"<<endl;
        }else{
            cout<<"No"<<endl;
        }
    }
    return 0;
}

2、其他思路:

其实这种题目本身考量的就是对多种情形的分类讨论

这里也就不在多讨论。不过值得一提的是,经过对多个同学的分析,我发现这道水题一般写的快的学生,
大部分都是在进行单纯的分类讨论。针对上述的第一种思路,并没有多少人这样写。而写得稍慢的学生却
出现了有提交该思路代码的现象。

OK

原文地址:https://www.cnblogs.com/savennist/p/13746891.html