分析
我们可以将所有的b[i^j]直接对应到b[f(i^j)]上
于是显然可以fwt
我们对b进行t次fwt之后直接将答案与e0卷起来即可
注意由于模数不确定,我们可以将模数扩大$2^m$然后ifwt是直接除掉这个数即可
此题还要使用快速乘
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
int m,t,mod,n,a[2100000],b[2100000],d[110];
inline void fwt(int a[],int f){
int i,j,k;
for(i=1;i<n;i<<=1)
for(j=0;j<n;j+=(i<<1))
for(k=0;k<i;k++){
int x=a[j+k],y=a[i+j+k];
a[j+k]=(x+y)%mod,a[i+j+k]=(x+mod-y)%mod;
}
if(f==-1)for(i=0;i<n;i++)a[i]/=n;
}
inline int mul(int x,int y){
int res=(x*y-(int)((long double)x/mod*y)*mod);
return res<0?res+mod:res;
}
inline int pw(int x,int p){
int res=1;
while(p){
if(p&1)res=mul(res,x);
x=mul(x,x);
p>>=1;
}
return res;
}
signed main(){
int i,j,k;
scanf("%I64d%I64d%I64d",&m,&t,&mod);
n=(1ll<<m);
mod*=n;
for(i=0;i<n;i++)scanf("%I64d",&a[i]);
for(i=0;i<=m;i++)scanf("%I64d",&d[i]);
for(i=0;i<n;i++){
k=0;
for(j=0;j<m;j++)
if((1<<j)&i)k++;
b[i]=d[k];
}
fwt(a,1),fwt(b,1);
for(i=0;i<n;i++)b[i]=pw(b[i],t);
for(i=0;i<n;i++)a[i]=mul(a[i],b[i]);
fwt(a,-1);
mod/=n;
for(i=0;i<n;i++)printf("%I64d
",a[i]%mod);
return 0;
}