Codeforces Round #717 (Div. 2) C Baby Ehab Partitions Again(思维)
题意:
给出一个数组,如果数组中其中一些数的和等于剩下数的和,那么数组就是坏的,问最小要删去几个数才能使得数组是好的。
题解:
如果数组的和 s u m sum sum为奇数,那么一定是好的。
如果为偶数,可以先用类似于背包的 d p dp dp求出是否有一些数相加为 s u m / 2 sum/2 sum/2 。
如果有,如果数组中存在奇数,那么删去这个奇数,就一定满足条件。如果不存在奇数,假设我要删去 x x x,那么如果 x / 2 x/2 x/2 存在,那么就得把先 x / 2 x/2 x/2 删去,把 x / 2 x/2 x/2 删去时,又得考虑 x / 4 x/4 x/4 ,以此类推,那么其实只要删去一直除 2 2 2 最快变为奇数的数,就一定满足条件。
证明:假设这个数是 x x x,那么这个数 x / 2 x/2 x/2 就一定不存在, 如果存在, x / 2 x/2 x/2 一直除2直到变为奇数的次数一定比 x x x 少,那最优解就不是 x x x了。所以一定不存在 x / 2 x/2 x/2 ,那么最后把 x x x删去就不可能使得两边的和还能相等。
代码:
#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=2e5+5;
const int inf=0x3f3f3f3f;
int dp[2][MAXN];
int a[MAXN];
int num[MAXN];
int main()
{
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
int temp=a[i];
while(temp%2==0)
{
num[i]++;
temp/=2;
}
}
dp[1][0]=1;
int f=1;
for(int i=1;i<=n;i++)
{
for(int j=2e5;j>=0;j--)
{
if(dp[f][j])
{
dp[f^1][j+a[i]]=1;
dp[f^1][j]=1;
}
}
f^=1;
}
if(sum&1)
{
printf("%d\n",0);
}
else if(dp[f][sum/2]==0)
{
printf("%d\n",0);
}
else
{
printf("%d\n",1);
int ans=1e9;
int pos;
for(int i=1;i<=n;i++)
{
if(num[i]<ans)
{
ans=num[i];
pos=i;
}
}
printf("%d\n",pos);
}
}

浙公网安备 33010602011771号