标签:long void pre for 传送门 cti return math ++
因为三个候选人实际上是一样的
所以我们只需要求出一个人的答案乘以\(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;
}
标签:long void pre for 传送门 cti return math ++
原文地址:https://www.cnblogs.com/loney-s/p/13131966.html