453D Little Pony and Elements of Harmony

传送门

分析

我们可以将所有的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\n",a[i]%mod);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/10507772.html