CF850E Random Elections
Posted Scx117
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF850E Random Elections相关的知识,希望对你有一定的参考价值。
题意:一共有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的主要内容,如果未能解决你的问题,请参考以下文章
cf 1020 round 503(SIS div2) C. Elections