题解:CF2211D AND-array
更好的阅读体验
逆天 polynomial 做法,做了一整场,糖完了。
首先我们先思考,假设已经知道了序列
那么我们可以按位考虑。假设我们考虑第
所以
很显然推出
假设
施加二项式反演可以变成
可以
考虑计算第二类斯特林数·行的手法,拆开组合数,变成
考虑构造
构造
这样子
那么这道题就做完了。贺一个任意模数多项式乘法板子,复杂度
#include<bits/stdc++.h>
#define endl '\n'
#define N 1000006
#define MOD 1000000007
using namespace std;
namespace poly
{
long double const pi=acos(-1);
struct comp
{
long double r,i;
comp(){r=i=0;}
comp(long double x,long double y){r=x,i=y;}
comp conj(){return comp(r,-i);}
friend comp operator +(comp x,comp y){return comp(x.r+y.r,x.i+y.i);}
friend comp operator -(comp x,comp y){return comp(x.r-y.r,x.i-y.i);}
friend comp operator *(comp x,comp y){return comp(x.r*y.r-x.i*y.i,x.i*y.r+x.r*y.i);}
};
typedef long long ll;
int r[1000005];
comp a[1000005],b[1000005],c[1000005],d[1000005];
void fft(comp *f,int n,int op)
{
for(int i=1;i<n;i++)r[i]=(r[i>>1]>>1)+((i&1)?(n>>1):0);
for(int i=1;i<n;i++)if(i<r[i])swap(f[i],f[r[i]]);
for(int len=2;len<=n;len<<=1)
{
int q=len>>1;
comp wn=comp(cos(pi/q),op*sin(pi/q));
for(int i=0;i<n;i+=len)
{
comp w=comp(1,0);
for(int j=i;j<i+q;j++,w=w*wn)
{
comp d=f[j+q]*w;
f[j+q]=f[j]-d;
f[j]=f[j]+d;
}
}
}
}
void mtt(int *f,int *g,int *h,int n,int p)
{
for(int i=0;i<=n;i++)r[i]=0,a[i]=b[i]=c[i]=d[i]={0,0};
for(int i=0;i<n;i++)
a[i].r=(f[i]>>15),a[i].i=(f[i]&32767),
c[i].r=(g[i]>>15),c[i].i=(g[i]&32767);
fft(a,n,1),fft(c,n,1);
for(int i=1;i<n;i++)b[i]=a[n-i].conj();
b[0]=a[0].conj();
for(int i=1;i<n;i++)d[i]=c[n-i].conj();
d[0]=c[0].conj();
for(int i=0;i<n;i++)
{
comp
aa=(a[i]+b[i])*comp(0.5,0),
bb=(a[i]-b[i])*comp(0,-0.5),
cc=(c[i]+d[i])*comp(0.5,0),
dd=(c[i]-d[i])*comp(0,-0.5);
a[i]=aa*cc+comp(0,1)*(aa*dd+bb*cc),b[i]=bb*dd;
}
fft(a,n,-1),fft(b,n,-1);
for(int i=0;i<n;i++)
{
int
aa=(ll)(a[i].r/n+0.5)%p,
bb=(ll)(a[i].i/n+0.5)%p,
cc=(ll)(b[i].r/n+0.5)%p;
h[i]=((1ll*aa*(1<<30)+1ll*bb*(1<<15)+cc)%p+p)%p;
}
}
}
int fac[N],ifac[N];
inline int qpow(int x,int y=MOD-2)
{
int ret=1;
for(;y;y>>=1,x=1ll*x*x%MOD)if(y&1)ret=1ll*ret*x%MOD;
return ret;
}
inline int binom(int x,int y) {return x<y?0:1ll*fac[x]*ifac[y]%MOD*ifac[x-y]%MOD;}
int n,f[N],g[N];
int a[N],b[N],c[N],ans[N];
void solve()
{
scanf("%d",&n);
int lim=1;
while(lim<=(n+n))lim<<=1;
for(int i=0;i<=lim;i++)a[i]=b[i]=c[i]=0;
for(int i=1;i<=n;i++)scanf("%d",&f[i]),ans[i]=0;
for(int i=0;i<=n;i++)
{
if(i)a[i]=1ll*fac[i]*f[i]%MOD;
b[n-i]=ifac[i]; if(i&1)b[n-i]=MOD-b[n-i];
}
poly::mtt(a,b,c,lim,1e9+7);
for(int i=1;i<=n;i++)
{
int now=1ll*c[i+n]*ifac[i]%MOD;
for(int j=0;j<=30;j++)if(now>>j&1)
for(int k=1;k<=i;k++)ans[k]|=1<<j;
}
for(int i=1;i<=n;i++)printf("%d%c",ans[i]," \n"[i==n]);
}
main()
{
fac[0]=1;
for(int i=1;i<N;i++)fac[i]=1ll*fac[i-1]*i%MOD;
ifac[N-1]=qpow(fac[N-1]);
for(int i=N-2;~i;i--)ifac[i]=1ll*ifac[i+1]*(i+1)%MOD;
int T; scanf("%d",&T);
while(T--)solve();
return 0;
}