题意:
出n个数,将n个数分成k个不相交集合,并且其中恰好有p个集合的元素之和为偶数,输出分解方案。
题解:
题目要求p个集合偶数和,那么就有q=k-p个集合奇数和。
奇+奇=偶
奇+偶=奇
偶+偶=偶
所以和为奇数的集合里必须包含奇数个奇数,故第一个无解的情况为:奇数的个数<q。
对于多出来的奇数,可以偶数个奇数组成偶数,以此来不扰乱偶数的组合,但是在组成完成q个奇数集合后,剩下的奇数如果是奇数个,那么就是第二个无解的情况:
(奇数的个数-q)%2!=0.
如果按照上面的方法组成的集合个数小于k,则也是无解。
接下来就是构造,先处理奇数,再处理偶数就好了。
/**************** *PID:439c div2 *Auth:Jonariguez ***************** */ #define lson k*2,l,m #define rson k*2+1,m+1,r #define rep(i,s,e) for(i=(s);i<=(e);i++) #define For(j,s,e) For(j=(s);j<(e);j++) #define sc(x) scanf("%d",&x) #define In(x) scanf("%I64d",&x) #define pf(x) printf("%d",x) #define pfn(x) printf("%d\n",(x)) #define Pf(x) printf("%I64d",(x)) #define Pfn(x) printf("%I64d\n",(x)) #define Pc printf(" ") #define PY puts("YES") #define PN puts("NO") #include <stdio.h> #include <string.h> #include <string> #include <math.h> #include <set> #include <map> #include <stack> #include <queue> #include <vector> #include <iostream> #include <algorithm> using namespace std; typedef __int64 LL; typedef int Ll; Ll quick_pow(Ll a,Ll b,Ll MOD){a%=MOD;Ll res=1;while(b){if(b&1)res=(res*a)%MOD;b/=2;a=(a*a)%MOD;}return res;} const int maxn=100000+10; int a[maxn]; vector<int> odd,eve; int main() { int i,j,n,k,p; while(scanf("%d%d%d",&n,&k,&p)!=EOF){ odd.clear();eve.clear(); int ji=0,ou=0; for(i=1;i<=n;i++){ scanf("%d",&a[i]); if(a[i]&1){ ji++;odd.push_back(a[i]); }else { ou++;eve.push_back(a[i]); } } int q=k-p; if(ji<q || ji>=q && (ji-q)&1){ puts("NO");continue; } if(q+(ji-q)/2+ou<k){ puts("NO");continue; } PY; if(p==0){ for(i=0;i<k-1;i++) printf("1 %d\n",odd[i]); printf("%d",n-k+1); for(;i<odd.size();i++) printf(" %d",odd[i]); for(i=0;i<eve.size();i++) printf(" %d",eve[i]); puts("");continue; }else if(q==0){ if(eve.size()>=k-1){ for(i=0;i<k-1;i++) printf("1 %d\n",eve[i]); printf("%d",n-k+1); for(;i<eve.size();i++) printf(" %d",eve[i]); for(i=0;i<odd.size();i++) printf(" %d",odd[i]); puts("");continue; }else { int cnt=0; for(i=0;i<eve.size();i++){ printf("1 %d\n",eve[i]); cnt++; } int temp=eve.size(); j=0; for(i=temp+1;i<=k-1;i++){ printf("2 "); printf("%d %d\n",odd[j],odd[j+1]); cnt+=2;j+=2; } if(n-cnt>0){ printf("%d",n-cnt); for(;j<odd.size();j++) printf(" %d",odd[j]); puts(""); } continue; } } int cnt=0; for(i=0;i<q;i++){ printf("1 %d\n",odd[i]); cnt++; } if(ou<p){ for(i=0;i<eve.size();i++){ printf("1 %d\n",eve[i]); cnt++; } int c=eve.size()+1; for(i=q;c<p && i<odd.size();i+=2){ printf("2 %d %d\n",odd[i],odd[i+1]); c++;cnt+=2; } printf("%d",n-cnt); for(;i<odd.size();i++) printf(" %d",odd[i]); puts(""); }else { for(i=0;i<p-1;i++){ printf("1 %d\n",eve[i]);cnt++; } printf("%d",n-cnt); for(;i<eve.size();i++) printf(" %d",eve[i]); for(i=q;i<odd.size();i++) printf(" %d",odd[i]); puts(""); } } return 0; } /* 8 4 4 1 1 1 1 1 1 1 1 */