FFT:https://www.lydsy.com/JudgeOnline/problem.php?id=2179
#include<bits/stdc++.h> #define pi acos(-1) using namespace std; typedef complex<double>cp; int n,m,L,R[131078],ans[131078]; cp a[131078],b[131078]; char s[131078]; void fft(cp *a,int f) { for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<n;i<<=1) { cp wn(cos(pi/i),f*sin(pi/i)); for(int p=i*2,j=0;j<n;j+=p) { cp w(1,0); for(int k=0;k<i;k++,w*=wn) { cp x=a[j+k],y=w*a[j+k+i]; a[j+k]=x+y;a[j+k+i]=x-y; } } } } int main() { scanf("%d",&n); scanf("%s",s); for(int i=0;i<n;i++)a[n-i-1]=s[i]-'0'; scanf("%s",s); for(int i=0;i<n;i++)b[n-i-1]=s[i]-'0'; n--;m=n*2; for(n=1;n<=m;n*=2)L++; for(int i=0;i<n;i++)R[i]=(R[i/2]/2)|((i&1)<<L-1); fft(a,1);fft(b,1); for(int i=0;i<=n;i++)a[i]=a[i]*b[i]; fft(a,-1); int x=0; for(int i=0;i<=m;i++) ans[i]=(int)(a[i].real()/n+0.5); for(int i=0;i<=m;i++) ans[i+1]+=ans[i]/10,ans[i]%=10; if(ans[m+1])m++; for(int i=m;i>=0;i--)printf("%d",ans[i]); }
NTT与FFT类似就没了
分治NTT:https://www.luogu.org/problemnew/show/P4721
#include<bits/stdc++.h> using namespace std; const int N=53e4,mod=998244353; int n,a[N],A[N],B[N],f[N],R[N]; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod,b>>=1; } return ret; } void init(int L){for(int i=0;i<(1<<L);i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);} void NTT(int*a,int n,int tp) { for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<n;i<<=1) { int wn=qpow(3,mod/(i<<1)); if(tp==-1)wn=qpow(wn,mod-2); for(int j=0;j<n;j+=i<<1) for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod) { int x=a[j+k],y=1ll*a[i+j+k]*w%mod; a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod; } } if(tp==1)return; int inv=qpow(n,mod-2); for(int i=0;i<n;i++)a[i]=1ll*a[i]*inv%mod; } void cdq(int l,int r) { if(l==r)return; int mid=l+r>>1; cdq(l,mid); int L=1,now=1,nn; while(now<=r-l+1)now*=2,L++; init(L); nn=1<<L; for(int i=0;i<=nn;i++)A[i]=B[i]=0; for(int i=l;i<=mid;i++)A[i-l]=f[i]; for(int i=1;i<=r-l;i++)B[i-1]=a[i]; NTT(A,nn,1),NTT(B,nn,1); for(int i=0;i<=nn;i++)A[i]=1ll*A[i]*B[i]%mod; NTT(A,nn,-1); for(int i=mid+1;i<=r;i++)f[i]=(f[i]+A[i-l-1])%mod; cdq(mid+1,r); } int main() { scanf("%d",&n); f[0]=1; for(int i=1;i<n;i++)scanf("%d",&a[i]); cdq(0,n-1); for(int i=0;i<n;i++)printf("%d ",f[i]); }
FWT:https://www.luogu.org/problemnew/show/P4717
#include<bits/stdc++.h> using namespace std; const int mod=998244353,inv2=499122177,N=1<<17; int n,all,a[N],b[N],c[N],d[N]; void FWT_or(int*a,int n,int f) { for(int i=1;i<n;i*=2) for(int j=0;j<n;j+=i*2) for(int k=0;k<i;k++) { int x=a[j+k],y=a[j+k+i]; a[j+k+i]=f==1?(x+y)%mod:(y-x+mod)%mod; } } void FWT_and(int*a,int n,int f) { for(int i=1;i<n;i*=2) for(int j=0;j<n;j+=i*2) for(int k=0;k<i;k++) { int x=a[j+k],y=a[j+k+i]; a[j+k]=f==1?(x+y)%mod:(x-y+mod)%mod; } } void FWT_xor(int*a,int n,int f) { for(int i=1;i<n;i*=2) for(int j=0;j<n;j+=i*2) for(int k=0;k<i;k++) { int x=a[j+k],y=a[j+k+i]; a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod; if(f==-1) { a[j+k]=1ll*a[j+k]*inv2%mod; a[j+k+i]=1ll*a[j+k+i]*inv2%mod; } } } int main() { scanf("%d",&n);all=1<<n; for(int i=0;i<all;i++)scanf("%d",&a[i]),c[i]=a[i]; for(int i=0;i<all;i++)scanf("%d",&b[i]),d[i]=b[i]; FWT_or(c,all,1);FWT_or(d,all,1); for(int i=0;i<all;i++)c[i]=1ll*c[i]*d[i]%mod; FWT_or(c,all,-1); for(int i=0;i<all;i++)printf("%d ",c[i]); puts(""); memcpy(c,a,sizeof c); memcpy(d,b,sizeof d); FWT_and(c,all,1);FWT_and(d,all,1); for(int i=0;i<all;i++)c[i]=1ll*c[i]*d[i]%mod; FWT_and(c,all,-1); for(int i=0;i<all;i++)printf("%d ",c[i]); puts(""); memcpy(c,a,sizeof c); memcpy(d,b,sizeof d); FWT_xor(c,all,1);FWT_xor(d,all,1); for(int i=0;i<all;i++)c[i]=1ll*c[i]*d[i]%mod; FWT_xor(c,all,-1); for(int i=0;i<all;i++)printf("%d ",c[i]); }
任意模数NTT:https://www.luogu.org/problemnew/show/P4245
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int P1=469762049,P2=998244353,P3=1004535809,N=3e6+7; const ll PP=1ll*P1*P2; int n,m,p,len=1,L,A[N],B[N],C[N],D[N],ans[3][N],R[N]; ll qmul(ll a,ll b,ll mod) { a%=mod;b%=mod; ll ret=0; while(b) { if(b&1)ret=(ret+a)%mod; a=(a+a)%mod;b>>=1; } return ret; } int qpow(int a,int b,int mod) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod;b>>=1; } return ret; } void NTT(int*A,int n,int f,int mod) { for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]); for(int i=1;i<n;i*=2) { int wn=qpow(f==1?3:qpow(3,mod-2,mod),(mod-1)/(i<<1),mod); for(int j=0;j<n;j+=i*2) for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod) { int x=A[j+k],y=1ll*w*A[i+j+k]%mod; A[j+k]=(x+y)%mod; A[i+j+k]=(x-y+mod)%mod; } } if(f==-1) { int inv=qpow(n,mod-2,mod); for(int i=0;i<n;i++)A[i]=1ll*A[i]*inv%mod; } } int main() { scanf("%d%d%d",&n,&m,&p); for(int i=0;i<=n;i++)scanf("%d",&A[i]); for(int i=0;i<=m;i++)scanf("%d",&B[i]); while(len<=n+m)len<<=1,L++; for(int i=0;i<=len;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1); copy(A,A+n+1,C);copy(B,B+m+1,D); NTT(C,len,1,P1);NTT(D,len,1,P1); for(int i=0;i<=len;i++)ans[0][i]=1ll*C[i]*D[i]%P1; memset(C,0,sizeof C);memset(D,0,sizeof D); copy(A,A+n+1,C);copy(B,B+m+1,D); NTT(C,len,1,P2);NTT(D,len,1,P2); for(int i=0;i<=len;i++)ans[1][i]=1ll*C[i]*D[i]%P2; memset(C,0,sizeof C);memset(D,0,sizeof D); copy(A,A+n+1,C);copy(B,B+m+1,D); NTT(C,len,1,P3);NTT(D,len,1,P3); for(int i=0;i<=len;i++)ans[2][i]=1ll*C[i]*D[i]%P3; NTT(ans[0],len,-1,P1); NTT(ans[1],len,-1,P2); NTT(ans[2],len,-1,P3); for(int i=0;i<=n+m;i++) { ll A=(qmul(1ll*ans[0][i]*P2%PP,qpow(P2%P1,P1-2,P1),PP)+qmul(1ll*ans[1][i]*P1%PP,qpow(P1%P2,P2-2,P2),PP))%PP; ll K=((ans[2][i]-A)%P3+P3)%P3*qpow(PP%P3,P3-2,P3)%P3; printf("%d ",(A%p+K%p*(PP%p)%p)%p); } }
多项式求逆:https://www.luogu.org/problemnew/show/P4238
#include<bits/stdc++.h> using namespace std; const int mod=998244353,N=4e5+7; int a[N],b[N],c[N],R[N]; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod;b>>=1; } return ret; } void NTT(int*a,int n,int f) { for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<n;i*=2) { int wn=qpow(3,(mod-1)/(i*2)); for(int j=0;j<n;j+=i*2) { int w=1; for(int k=0,x,y;k<i;k++,w=1ll*w*wn%mod) { x=a[j+k];y=1ll*w*a[j+k+i]%mod; a[j+k]=(x+y)%mod;a[j+k+i]=((x-y)%mod+mod)%mod; } } } if(f==1)return; int nv=qpow(n,mod-2); reverse(a+1,a+n); for(int i=0;i<n;i++)a[i]=1ll*a[i]*nv%mod; } void inv(int deg,int*a,int*b) { if(deg==1){b[0]=qpow(a[0],mod-2);return;} inv((deg+1)/2,a,b); int L=0,n=1; while(n<deg*2)n*=2,L++; for(int i=1;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1)); for(int i=0;i<deg;i++)c[i]=a[i]; for(int i=deg;i<n;i++)c[i]=0; NTT(c,n,1);NTT(b,n,1); for(int i=0;i<n;i++)b[i]=((2ll-1ll*c[i]*b[i]%mod)+mod)*b[i]%mod; NTT(b,n,-1); for(int i=deg;i<n;i++)b[i]=0; } int main() { int n;scanf("%d",&n); for(int i=0;i<n;i++)scanf("%d",&a[i]); inv(n,a,b); for(int i=0;i<n;i++)printf("%d ",b[i]); }
多项式开根:https://www.luogu.org/problemnew/show/P5205
#include<bits/stdc++.h> using namespace std; const int N=4e5+7,mod=998244353,inv2=499122177; int n,f[N],g[N],A[N],B[N],C[N],D[N],R[N]; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod,b>>=1; } return ret; } void NTT(int *a,int n,int tp) { for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<n;i<<=1) { int wn=qpow(3,mod/(i<<1)); if(tp==-1)wn=qpow(wn,mod-2); for(int j=0;j<n;j+=i<<1) for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod) { int x=a[j+k],y=1ll*a[i+j+k]*w%mod; a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod; } } if(tp==1)return; int invn=qpow(n,mod-2); for(int i=0;i<n;i++)a[i]=1ll*a[i]*invn%mod; } void inv(int*a,int*b,int n) { b[0]=qpow(a[0],mod-2); int len,lim; for(len=1;len<(n<<1);len<<=1) { lim=len<<1; for(int i=0;i<len;i++)A[i]=a[i],B[i]=b[i]; for(int i=0;i<lim;i++)R[i]=(R[i>>1]>>1)|((i&1)?len:0); NTT(A,lim,1),NTT(B,lim,1); for(int i=0;i<lim;i++)b[i]=(2-1ll*A[i]*B[i]%mod+mod)*B[i]%mod; NTT(b,lim,-1); for(int i=len;i<lim;i++)b[i]=0; } for(int i=0;i<len;i++)A[i]=B[i]=0; for(int i=n;i<len;i++)b[i]=0; } void Sqrt(int*a,int*b,int n) { b[0]=1; int *A=C,*B=D,len,lim; for(len=1;len<(n<<1);len<<=1) { lim=len<<1; for(int i=0;i<len;i++)A[i]=a[i]; inv(b,B,lim>>1); for(int i=0;i<lim;i++)R[i]=(R[i>>1]>>1)|((i&1)?len:0); NTT(A,lim,1);NTT(B,lim,1); for(int i=0;i<lim;i++)A[i]=1ll*A[i]*B[i]%mod; NTT(A,lim,-1); for(int i=0;i<len;i++)b[i]=1ll*(b[i]+A[i])%mod*inv2%mod; for(int i=len;i<lim;i++)b[i]=0; } for(int i=0;i<len;i++)A[i]=B[i]=0; for(int i=n;i<len;i++)b[i]=0; } int main() { scanf("%d",&n); for(int i=0;i<n;i++)scanf("%d",&f[i]); Sqrt(f,g,n); for(int i=0;i<n;i++)printf("%d ",g[i]); }
多项式求ln:https://www.luogu.org/problemnew/show/P4725
#include<bits/stdc++.h> using namespace std; const int N=4e5+7,mod=998244353,inv2=499122177; int n,nn,L,a[N],b[N],c[N],d[N],inv[N],R[N]; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod,b>>=1; } return ret; } void NTT(int*a,int f) { for(int i=0;i<nn;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<nn;i<<=1) { int wn=qpow(3,mod/(i<<1)); if(f==-1)wn=qpow(wn,mod-2); for(int j=0;j<nn;j+=i<<1) for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod) { int x=a[j+k],y=1ll*a[i+j+k]*w%mod; a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod; } } if(f==1)return; int invn=qpow(nn,mod-2); for(int i=0;i<nn;i++)a[i]=1ll*a[i]*invn%mod; } void getinv(int*a,int*b,int n) { if(n==1){b[0]=qpow(a[0],mod-2);return;} getinv(a,b,n+1>>1); nn=1,L=0;while(nn<(n<<1))nn<<=1,L++; for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1); for(int i=0;i<nn;i++)c[i]=i<n?a[i]:0; for(int i=n+1>>1;i<nn;i++)b[i]=0; NTT(b,1),NTT(c,1); for(int i=0;i<nn;i++)b[i]=(mod+2-1ll*b[i]*c[i]%mod)%mod*b[i]%mod; NTT(b,-1); for(int i=n;i<nn;i++)b[i]=0; } void getln(int*a,int*b,int n) { getinv(a,b,n); nn=1,L=0;while(nn<(n<<1))nn<<=1,L++; for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1); for(int i=0;i<n-1;i++)d[i]=1ll*a[i+1]*(i+1)%mod; for(int i=n-1;i<nn;i++)d[i]=0; NTT(b,1),NTT(d,1); for(int i=0;i<nn;i++)b[i]=1ll*b[i]*d[i]%mod; NTT(b,-1); for(int i=n-1;i>0;i--)b[i]=1ll*b[i-1]*inv[i]%mod; for(int i=n;i<nn;i++)b[i]=0; b[0]=0; } int main() { scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]); inv[1]=1;for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; getln(a,b,n); for(int i=0;i<n;i++)printf("%d ",b[i]); }
多项式求exp(其实前面求ln全部包含于此了):https://www.luogu.org/problemnew/show/P4726
#include<bits/stdc++.h> using namespace std; const int N=4e5+7,mod=998244353,inv2=499122177; int n,nn,L,a[N],b[N],c[N],d[N],lnb[N],inv[N],R[N]; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod,b>>=1; } return ret; } void NTT(int*a,int f) { for(int i=0;i<nn;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int i=1;i<nn;i<<=1) { int wn=qpow(3,mod/(i<<1)); if(f==-1)wn=qpow(wn,mod-2); for(int j=0;j<nn;j+=i<<1) for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod) { int x=a[j+k],y=1ll*a[i+j+k]*w%mod; a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod; } } if(f==1)return; int invn=qpow(nn,mod-2); for(int i=0;i<nn;i++)a[i]=1ll*a[i]*invn%mod; } void getinv(int*a,int*b,int n) { if(n==1){b[0]=qpow(a[0],mod-2);return;} getinv(a,b,n+1>>1); nn=1,L=0;while(nn<(n<<1))nn<<=1,L++; for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1); for(int i=0;i<nn;i++)c[i]=i<n?a[i]:0; for(int i=n+1>>1;i<nn;i++)b[i]=0; NTT(b,1),NTT(c,1); for(int i=0;i<nn;i++)b[i]=(mod+2-1ll*b[i]*c[i]%mod)%mod*b[i]%mod; NTT(b,-1); for(int i=n;i<nn;i++)b[i]=0; } void getln(int*a,int*b,int n) { getinv(a,b,n); nn=1,L=0;while(nn<(n<<1))nn<<=1,L++; for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1); for(int i=0;i<n-1;i++)d[i]=1ll*a[i+1]*(i+1)%mod; for(int i=n-1;i<nn;i++)d[i]=0; NTT(b,1),NTT(d,1); for(int i=0;i<nn;i++)b[i]=1ll*b[i]*d[i]%mod; NTT(b,-1); for(int i=n-1;i>0;i--)b[i]=1ll*b[i-1]*inv[i]%mod; for(int i=n;i<nn;i++)b[i]=0; b[0]=0; } void getexp(int*a,int*b,int n) { if(n==1){b[0]=1;return;} getexp(a,b,(n+1)>>1); getln(b,lnb,n); nn=1,L=0;while(nn<(n<<1))nn<<=1,L++; for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1); for(int i=0;i<n;i++)lnb[i]=a[i]>=lnb[i]?a[i]-lnb[i]:a[i]-lnb[i]+mod; for(int i=n;i<nn;i++)lnb[i]=b[i]=0; lnb[0]++; NTT(b,1),NTT(lnb,1); for(int i=0;i<nn;i++)b[i]=1ll*b[i]*lnb[i]%mod; NTT(b,-1); for(int i=n;i<nn;i++)b[i]=0; } int main() { scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]); inv[1]=1;for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; getexp(a,b,n); for(int i=0;i<n;i++)printf("%d ",b[i]); }
咕了