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; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号