基础逻辑-分类讨论
比赛: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