bzoj 2194 快速傅里叶之二
而标准卷积是:
标准卷积是:下标之和为定值,而这里下标之差是定值,将b数组倒过来。
C[0] = C[n-1]
模板是绍兴一中NTT板子。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int maxn=210000; const LL P=998244353; const LL mod=998244353; const LL g=3; int N,na,nb; LL a[maxn*2],b[maxn*2],W[2][maxn*2],rev[maxn*2],f[maxn*2],tmp[maxn*2]; LL inv[410000]; LL ff[410000]; LL pow_mod(LL a,int b) { LL c=1; for (;b; b>>=1,a=a*a%P) if (b&1) c=c*a%P; return c; } void NTT(LL*a,int f,int N) { for (int i=0;i<N;i++) if (i<rev[i]) swap(a[i],a[rev[i]]); for (int i=1;i<N;i<<=1) for (int j=0,t=N/(i<<1);j<N;j+=i<<1) for (int k=0,l=0,x,y;k<i;k++,l+=t) x=(LL)W[f][l]*a[j+k+i]%P,y=a[j+k],a[j+k]=(y+x)%P,a[j+k+i]=(y-x+P)%P; if (f) for (int i=0,x=pow_mod(N,P-2);i<N;i++) a[i]=(LL)a[i]*x%P; } void change(int N) { for (int i=0;i<N;i++) { int x=i,y=0; for (int k=1; k<N; x>>=1,k<<=1) (y<<=1)|=x&1; rev[i]=y; } } void init(int N) { W[0][0]=W[1][0]=1; for (int i=1,x=pow_mod(g,(P-1)/N),y=pow_mod(x,P-2); i<N; i++) W[0][i]=(LL)x*W[0][i-1]%P,W[1][i]=(LL)y*W[1][i-1]%P; change(N); } int main() { //freopen("in.txt","r",stdin); int n; scanf("%d",&n); na = nb = n; N = 1; while(N<=na*2||N<=nb*2) N<<=1; init(N); for(int i=0;i<na;i++) { scanf("%I64d",&a[i]); scanf("%I64d",&b[nb-i-1]); } for(int i=na;i<N;i++) a[i] = 0; for(int i=nb;i<N;i++) b[i] = 0; NTT(a,0,N); NTT(b,0,N); for(int i=0;i<N;i++) a[i] = a[i]*b[i]%mod; NTT(a,1,N); for(int i=0;i<n;i++) printf("%I64d\n",a[i+n-1]); return 0; }