首页 > 其他 > 详细

Codeforces 1242C

时间:2020-02-14 23:45:42      阅读:101      评论:0      收藏:0      [点我收藏+]

先判一下能不能均分,不能就gg,否则设平均数为\(ave\),第\(i\)个盒子中的数的和为\(sum_i\)

然后考虑枚举一个盒子中扔掉一个数\(x\),那么由于所有数两两不同,那么可以找到一个唯一的\(y\)扔进这个盒子,使其等于\(ave\)

这里显然可以通过\(sum_i+y-x=ave\)反解出\(y=ave+x-sum_i\)

这样不停的找前驱,就是一个找环的过程

然后如果一个环能闭上,那么就是一个合法的集合

对于集合之间,最后做一次子集DP就行了

输出方案的话记一下DP的前驱状态和每个合法集合的构成即可

复杂度\(O(k^2n+3^k)\)

技术分享图片
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int k;
 5 ll s,sum[16];
 6 vector<ll> a[16];
 7 unordered_map<ll,int> has[16];
 8 bool vis[16];
 9 bool iscir[40005],dp[40005];
10 int pp[40005];
11 struct Node
12 {
13     int from,to;
14     ll val;
15     Node(int F=0,int T=0,ll V=0){from=F;to=T;val=V;}
16 };
17 bool operator < (Node A,Node B){return A.from<B.from;}
18 vector<Node> Ans[40005];
19 void go(int pos,ll val)
20 {
21     memset(vis,0,sizeof(vis));
22     int u=pos;
23     ll w=s+val-sum[u];
24     vector<Node> tmp;tmp.clear();
25     while(1)
26     {
27         int pre=-1;
28         for(int i=0;i<k;++i)if(has[i][w]){pre=i;break;}
29         if(pre==-1)return;
30         tmp.push_back(Node(pre,u,w));
31         u=pre;
32         if(vis[u])return;
33         vis[u]=1;
34         if(u==pos)break;
35         w=s+w-sum[u];
36     }
37     if(val!=w)return;
38     int S=0;
39     for(int i=0;i<k;++i)if(vis[i])S|=(1<<i);
40     iscir[S]=1;
41     Ans[S]=tmp;
42 }
43 vector<Node> res;
44 void print(int S)
45 {
46     if(!S)return;
47     for(Node u:Ans[S^pp[S]])res.push_back(u);
48     print(pp[S]);
49 }
50 int main()
51 {
52     scanf("%d",&k);
53     s=0;
54     for(int sz,i=0;i<k;++i)
55     {
56         scanf("%d",&sz);
57         while(sz--)
58         {
59             ll x;scanf("%I64d",&x);
60             a[i].push_back(x);
61             has[i][x]=1;
62             sum[i]+=x;
63         }
64         s+=sum[i];
65     }
66     if(s%k)puts("No");
67     else
68     {
69         s/=k; 
70         for(int i=0;i<k;++i)
71             for(ll x:a[i])go(i,x);
72         dp[0]=1;
73         for(int S=1;S<(1<<k);++S)
74         {
75             for(int s=S;s;s=(s-1)&S)if(dp[S^s]&iscir[s])
76             {
77                 dp[S]=1;
78                 pp[S]=S^s;
79             }
80         }
81         if(!dp[(1<<k)-1])puts("No");
82         else
83         {
84             puts("Yes");
85             res.clear();
86             print((1<<k)-1);
87             sort(res.begin(),res.end());
88             for(Node u:res)printf("%I64d %d\n",u.val,u.to+1);
89         }
90     }
91 }
View Code

 

Codeforces 1242C

原文:https://www.cnblogs.com/uuzlove/p/12310237.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!