zoukankan      html  css  js  c++  java
  • 【CF850E】Random Elections FWT

    【CF850E】Random Elections

    题意:有n位选民和3位预选者A,B,C,每个选民的投票方案可能是ABC,ACB,BAC...,即一个A,B,C的排列。现在进行三次比较,A-B,B-C,C-A。每次比较的结果由一个给定的函数决定$f(x):{0,1}^n ightarrow {0,1}$,即读入一个长度为n的bool数组,返回一个bool变量。假如是A和B比较,则读入数组的第i个bool是 第i个人的排列中,A是否在B的前面;返回的bool是 A获胜还是B获胜。现在给你函数f(一张包含2^n个bool的表),所有选民的方案都是随机的,问你有多少种方案使得 存在一个预选者获得2场胜利。

    如果嫌我说的太不清楚还是看原题吧~

    题解:假设A赢了两场,那么我们设两次比较时的bool数组为$A-B:P_1$和$A-C:P_2$,考虑第i个人:

    如果在$P_1$中这个人是0,在$P_2$中这个人是0,那么这个人可能的投票方案为CBA,BCA
    同理得到:
    (0,0)->CBA,BCA
    (0,1)->BAC
    (1,0)->CAB
    (1,1)->ABC,ACB
    所以说,如果$P_1 mathrm{xor} P_2$中有cnt个1
    ,那么投票方案就是$2^{n-cnt}$。

    也就是说我们把f数组和自身做一下异或卷积,然后把每一个数的值$ imes 2^{n-cnt}$加到一起即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const ll P=1000000007;
    const int maxn=(1<<20)+4;
    int n,l;
    ll ans;
    int cnt[maxn];
    ll a[maxn];
    char str[maxn];
    inline void fwt()
    {
    	int h,i,j;
    	ll x,y;
    	for(h=2;h<=l;h<<=1)	for(i=0;i<l;i+=h)	for(j=i;j<i+h/2;j++)	x=a[j],y=a[j+h/2],a[j]=x+y,a[j+h/2]=x-y;
    }
    inline void ufwt()
    {
    	int h,i,j;
    	ll x,y;
    	for(h=2;h<=l;h<<=1)	for(i=0;i<l;i+=h)	for(j=i;j<i+h/2;j++)	x=a[j],y=a[j+h/2],a[j]=(x+y)/2,a[j+h/2]=(x-y)/2;
    }
    int main()
    {
    	scanf("%d",&n),l=1<<n;
    	int i;
    	scanf("%s",str);
    	for(i=0;i<l;i++)	a[i]=str[i]-'0';
    	fwt();
    	for(i=0;i<l;i++)	a[i]=a[i]*a[i];
    	ufwt();
    	ans=a[0]*l%P;
    	for(i=1;i<l;i++)	cnt[i]=cnt[i-(i&-i)]+1,ans=(ans+a[i]*(1<<(n-cnt[i])))%P;
    	printf("%lld",ans*3%P);
    	return 0;
    }
  • 相关阅读:
    二次冲刺站立会议七
    二次冲刺站立会议六
    二次冲刺站立会议五
    二次冲刺站立会议四
    二次冲刺站立会议三
    二次冲刺站立会议二
    二次冲刺站立会议一
    Linux课程学习总结
    仿知乎专栏的软件系统设计方案
    仿知乎专栏的需求分析和概念原型
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8282928.html
Copyright © 2011-2022 走看看