最骚的是我考场上做完之后睡了一觉,起来之后半天想不通自己在做什么
题解(重点只有一个)
显然的卷积
记 中的每一个元素
到数组
中
于是当前 ,十分显然的卷积-> NTT
然后处理
我们有
但同时我们也有
也就是说,卷积满足结合律、
然后我们就能对
进行快速幂!!
于是乎,这个问题就成了
附上代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=33000;
const int mod=(453<<21)+1,G=7,inv_G=135715694;
int n,m,k,N,inv_N,rev[maxn];
int KSM(int a,int b)
{
int res=1;
for (;b;b>>=1,a=1ll*a*a%mod)
if (b&1) res=1ll*res*a%mod;
return res;
}
int rever(int x)
{
int len=N,res=0;
while (len--) res<<=1,res^=(x&1),x>>=1;
return res;
}
struct DFT
{
int a[maxn];
void ntt(int op){
for (int i=0;i<N;i++) if (rev[i]>i) swap(a[rev[i]],a[i]);
int g=op==1?G:inv_G;
for (int sz=2;sz<=N;sz<<=1)
{
int t=KSM(g,(mod-1)/sz);
for (int bg=0;bg<N;bg+=sz)
{
for (int po=bg,w=1;po<bg+(sz>>1);po++)
{
int x=a[po],y=1LL*a[po+(sz>>1)]*w%mod;
a[po]=(x+y)%mod,a[po+(sz>>1)]=(x-y+mod)%mod;
w=1ll*w*t%mod;
}
}
}
if (op==-1) for (int i=0;i<N;++i) a[i]=1LL*a[i]*inv_N%mod;
}
}a,f;
void KSM(DFT f,DFT a)
{
for (;k;k>>=1)
{
a.ntt(1);
if (k&1)
{
f.ntt(1); for (int i=0;i<N;i++) f.a[i]=1ll*f.a[i]*a.a[i]%mod;
f.ntt(-1); for (int i=n;i<N;i++) f.a[i]=0;
}
for (int i=0;i<N;i++) a.a[i]=1ll*a.a[i]*a.a[i]%mod;
a.ntt(-1);
for (int i=n;i<N;i++) a.a[i]=0;
}
for (int i=0;i<n;i++) printf("%d ",f.a[i]);puts("");
}
int main()
{
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for (int i=0;i<n;i++) scanf("%d",&f.a[i]),f.a[i]%=mod;
for (int i=1,x;i<=m;i++) scanf("%d",&x),a.a[x]++;
N=(int)ceil(log2(n))+1;
for (int i=0;i<(1<<N);i++) rev[i]=rever(i);
//for (int i=0;i<(1<<N);i++) printf("%d %d\n",i,rev[i]);
N=1<<N,inv_N=KSM(N,mod-2),KSM(f,a);
return 0;
}
复制代码