题目大意
给出一个长度为 n n n 的序列,问最少需要删除多少个元素,满足剩下的序列不能分为两个元素和相等的集合
首先,我们用背包判断原序列是否已经满足要求
如果不满足,那么我们将证明只需要删去一个元素就可以让原序列满足要求 :
我们先考虑一个较为特殊的情况,也就是存在一个奇数的 a i a_i ai,那么我们只需要将这个奇数删去,这样剩下的元素和为奇数,就一定满足要求。
如果在这种特殊情况之外,那么就一定存在一个最大的
k
k
k,满足
2
k
∣
a
i
(
1
≤
i
≤
n
)
2^k|a_i \space (1\le i \le n)
2k∣ai (1≤i≤n)。为了方便计算,我们将原序列统一除以
2
k
2^k
2k,并删去一个奇数元素(可证此时一定有奇数)。此时,因为原序列所有数都是
2
k
2^k
2k 的倍数,所以一定会有奇数个
2
k
2^k
2k 无法被拆分,正如同上面所描述的特殊情况。
所以,我们只需要一个满足
a
i
2
k
m
o
d
2
=
1
\frac{a_i}{2^k} \mod 2=1
2kaimod2=1 的数即可
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int Maxn=110;
const int Maxm=200010;
bool f[Maxm];
int a[Maxn];
int n,m;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",a+i),m+=a[i];
f[0]=1;
for(int i=1;i<=n;++i)
for(int j=m;j>=a[i];--j)
f[j]|=f[j-a[i]];
if((m & 1) || !f[m>>1])
{puts("0");return 0;}
int ans=60,pos;
for(int i=1;i<=n;++i)
{
int tmp=0;
for(int j=30;j>=0;--j)
if(a[i]%(1<<j)==0){tmp=j;break;}
if(tmp<ans)ans=tmp,pos=i;
}
printf("1\n%d\n",pos);
return 0;
}