码迷,mamicode.com
首页 > 其他好文 > 详细

CF850E Random Elections

时间:2018-05-25 21:21:09      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:pre   c++   ||   结果   void   type   一个   dom   情况   

题意:一共有n个人,要在三个人中选prefer,一开始他们心中都会想好他们的排名(共6种),之后给出的判断不会矛盾。规则如下:一共有三轮,分别是a->b,b->c,c->a,每个人选1,表示prefer前者,选0表示prefer后者。这样形成一个n位的二进制x。定义函数f(x)={0,1}:1表示这一轮中前者赢,0表示后者赢。

有性质:f(x^((1<<n)-1))=1-f(x)。

现在给出f的对应值表,问其中一个人完胜(赢>=2局)的概率*6^n?n<=20。

 

标程:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int mod=1e9+7;
 4 typedef long long ll;
 5 const int N=1050000;
 6 int n;
 7 ll ans,f[N],x[N];
 8 void fwt()
 9 {
10     for (int i=0;i<n;i++)
11       for (int j=0;j<(1<<n);j++)
12         if (!(j&(1<<i)))
13         {
14             ll l=f[j],r=f[j|(1<<i)];
15             f[j]=l+r,f[j|(1<<i)]=l-r;
16          }
17 }
18 int main()
19 {
20     scanf("%d",&n);char c=getchar();
21     while (c<0||c>9) c=getchar();
22     for (int i=0;i<(1<<n);i++) f[i]=c-0,c=getchar();
23    fwt();
24    for (int i=0;i<(1<<n);i++) f[i]=f[i]*f[i]; 
25    fwt();
26    for (int i=0;i<(1<<n);i++) f[i]=f[i]>>n;
27    x[0]=1;
28    for (int i=1;i<(1<<n);i++) x[i]=x[i>>1]<<(i&1);//递推求2^popcount(i)
29    for (int i=0;i<(1<<n);i++)
30      ans=((ll)ans+(ll)f[i]*x[i^((1<<n)-1)]%mod)%mod;
31    printf("%d\n",(ll)ans*3%mod);
32     return 0;
33 }

易错点:1.有一点地方少开ll了啊啊啊。低级错误。

 

题解:fwt

写fwt的时候用a[i^j]=sigma(b[i]*c[j])来理解比较容易。

举其中一个人来看,设有关其的两轮他都赢(以下称作A,B),即有一个0一个1的结果(与题目中国的顺序对应)。(最后方案数*3,有三个人)

不能让喜爱排名矛盾,那么我们可以在A,B轮中任意,由此第三轮一些位置固定,一些位置不固定l个,*2^l即可。

运用题目中给的性质,一个0一个1的结果不好处理,但可以与两个1的情况通过一次取反唯一对应。于是可以用fwt统计方案数。由于是按位异或,答案下标的二进制表示中有几个0,即是有几个数不固定。

CF850E Random Elections

标签:pre   c++   ||   结果   void   type   一个   dom   情况   

原文地址:https://www.cnblogs.com/Scx117/p/9090360.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!