习题:Random Elections (DWT)
Posted loney-s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了习题:Random Elections (DWT)相关的知识,希望对你有一定的参考价值。
题目
思路
因为三个候选人实际上是一样的
所以我们只需要求出一个人的答案乘以(3)就行了
我们考虑A与B的比赛,和A与C的比赛
我们定义(1)为这个人在比赛中选了(A)
我们考虑每一个人的所有状态
((0,0)Rightarrow CBA,BCA\(0,1)Rightarrow BAC\(1,0)Rightarrow CAB\(1,1)Rightarrow ABC,ACB)
对于(f(x))的这个函数,实际上(x)为一种方案
也就是在A和B中,以及A和C中,(f(x))均为1
之后我们考虑怎么求方案
我们定义(g(x)=f(x)*f(x))
此时的乘法为按(xor)卷起来
对于一种下标,我们考虑有多少种可以构建出这个方案,
对于下标(i),我们定义(i)在二进制下0的个数为(cnt),方案即为(2^{cnt}*1^{n-cnt}=2^{cnt})
(ans=sum_{i=0}^{(1<<n)-1}2^{cnt}*g_i)
代码
#include<iostream>
using namespace std;
const int mod=1e9+7;
const int inv=(mod+1)/2;
namespace dwt
{
void dwtxor(int l,int r,long long *a)
{
if(l==r)
return;
int mid=(l+r)>>1;
long long t1,t2;
for(int i=l;i<=mid;i++)
{
t1=a[i];
t2=a[i-l+1+mid];
a[i]=(t1+t2)%mod;
a[i-l+1+mid]=(t1-t2+mod)%mod;
}
dwtxor(l,mid,a);
dwtxor(mid+1,r,a);
}
void idwtxor(int l,int r,long long *a)
{
if(l==r)
return;
int mid=(l+r)>>1;
idwtxor(l,mid,a);
idwtxor(mid+1,r,a);
long long t1,t2;
for(int i=l;i<=mid;i++)
{
t1=a[i];
t2=a[i-l+1+mid];
a[i]=(t1+t2)*inv%mod;
a[i-l+1+mid]=(t1-t2+mod)*inv%mod;
}
}
}
using namespace dwt;
int n,len;
long long a[(1<<21)+1];
long long ans;
string s;
int fj(int x)
{
int ret=0;
while(x)
{
if(x&1)
ret++;
x>>=1;
}
return 1<<(n-ret);
}
int main()
{
cin>>n;
cin>>s;
for(int i=0;i<s.length();i++)
a[i]=s[i]-‘0‘;
dwtxor(0,(1<<n)-1,a);
for(int i=0;i<(1<<n);i++)
a[i]=a[i]*a[i]%mod;
idwtxor(0,(1<<n)-1,a);
for(int i=0;i<(1<<n);i++)
ans=(ans+(a[i]*fj(i))%mod)%mod;
cout<<ans*3%mod;
return 0;
}
以上是关于习题:Random Elections (DWT)的主要内容,如果未能解决你的问题,请参考以下文章