CF1516C
C. Baby Ehab Partitions Again
这个题比 B 简单吧
比赛时花了 \(23\) 分钟切了。
其实我们可以得出结论,最多去掉一个数。
至于为什么需要在分析的过程中解释。
首先,如果 \(n\) 个数的和为奇数一定输出 \(0\)。这个很好理解。
其次,我们再来考虑是否存在一种划分方式满足一些数之和为 \(\frac{sum}{2}\)。这个其实很简单,裸的背包。没有这种划分方式输出 \(0\),否则要删掉一个数。
我们可能不发通过删除一个数导致无法划分,但是我们可以让 \(sum\) 的奇偶性发生改变。
如果此时全都是偶数,就 \(\div 2\),直到出现了奇数为止。
//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
const int MAXN=1e5;
int n,sum;
int a[MAXN];
bool f[2][MAXN];
void div() {
while(1) {
for(int i=1;i<=n;i++) {
if(a[i]&1) {
cout<<1<<endl<<i<<endl;
return ;
}
a[i]>>=1;
}
}
}
signed main() {
cin>>n;
for(int i=1;i<=n;i++) {
a[i]=read();
sum+=a[i];
}
if(sum&1) {
cout<<0<<endl;
return 0;
}
int m=sum/2;
fill(f[0],f[0]+m+1,0);
f[0][0]=1;
for(int i=1;i<=n;i++) {
for(int j=0;j<=m;j++) {
f[i%2][j]=f[(i-1)%2][j];
if(j>=a[i]) {
f[i%2][j]=f[i%2][j]|f[(i-1)%2][j-a[i]];
}
}
}
if(!f[n%2][m]) {
cout<<0<<endl;
return 0;
}
div();
return 0;
}