返回顶部

Codeforces Round #717 (Div. 2) C. Baby Ehab Partitions Again (数学,01背包)

  • 题意:给你\(n\)个数,问你最少删去多少个数,使得剩下的数任意分成两组,两组数的所有元素均不同.

  • 题解:我们先对这\(n\)个数求和,如果\(sum\)是奇数,那么我们不用删去任何元素.否则,我们对这\(n\)个数求整体的\(gcd\),并对所有数去掉这些\(gcd\).去掉后整体结果不变,但是其中一定会存在至少一个奇数,然后我们可以用01背包来判断是否合法,如果不合法就删去任意一个奇数即可.

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e7 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
     
    int n,V;
    int a[N];
    ll dp[N];
    int sum;
     
    bool check(){
    	dp[0]=1;
    	rep(i,1,n){
    		per(j,sum,a[i]){
    			dp[j]+=dp[j-a[i]];
    		}
    	}
     
    	if(dp[sum/2] && sum%2==0) return true;
    	return false;
    }
     
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	cin>>n;
     
    	int d=1;
    	rep(i,1,n){
    		cin>>a[i];
    		if(i==1) d=a[i];
    		else d=gcd(d,a[i]);
    	}
     
    	rep(i,1,n){
    		a[i]/=d;
    		sum+=a[i];
    	}
     
    	if(sum&1){
    		cout<<0<<'\n';
    		return 0;
    	}
     
    	int ans;
    	rep(i,1,n){
    		if(a[i]&1){
    			ans=i;
    			break;
    		}
    	}
     
    	if(check()){
    		cout<<1<<'\n';
    		cout<<ans<<'\n';
    		return 0;
    	}
     
    	cout<<0<<'\n';
     
     
     
        return 0;
    }
    
posted @ 2021-04-26 20:03  _Kolibri  阅读(50)  评论(0)    收藏  举报