**作者:tokitsukaze
链接:https://www.nowcoder.com/discuss/94787?type=101&order=0&pos=1&page=0
来源:牛客网
题解:
观察样例感觉是个卷积,然后发现是个xor的FWT。
题意转换成,给个a数组和c数组,求一个b数组,使得a数组和b数组做FWT后的结果为c数组。
然后观察FWT的过程:对a,b数组做FWT,c[i]=a[i]*b[i],然后对c数组做UFWT。
我们把这个过程倒过来:先对c数组做UFWT,然后对a数组做FWT,然后b[i]=c[i]/a[i],最后对b数组做FWT,就把b数组还原了。**
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read()
{
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=362148,mod=1e9+7;
int rev;
int n,a[N],b[N],c[N],v=0;
//void debug(int a[],int n)
//{
// cout<<"数组a为"<<endl;
// int top = 1;
// for(int i=0;i<=n;i++)
// {
// if(top)top =0;
// else printf(" ");
// printf("%d",a[i]);
// }
// printf("\n");
//}
int Pow(int x,int y)
{
int ans=1;
for (; y; y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
void FWT(int a[],int n)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
//xor:a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod;
//and:a[i+j]=x+y;
//or:a[i+j+d]=x+y;
}
}
void UFWT(int a[],int n)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
//rev表示2在模mod下的逆元
//xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
//and:a[i+j]=x-y;
//or:a[i+j+d]=y-x;
}
}
void solve(int a[],int b[],int n)
{
FWT(a,n);
FWT(b,n);
for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod;
UFWT(a,n);
}
signed main()
{
cin>>n;
rev = Pow(2,mod-2);
for(int i=0; i<n; i++)
scanf("%lld",&a[i]);
for(int j=0; j<n; j++)
{
scanf("%lld",&b[j]);
}
FWT(a,n);
FWT(b,n);
for(int i=0; i<n; i++)
{
a[i] = b[i]*Pow(a[i],mod-2)%mod;
}
UFWT(a,n);
for(int i=0; i<n; i++)
{
printf("%lld\n",a[i]);
}
return 0;
}