多项式算法:
FFT:
#include<bits/stdc++.h> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int N=3000050; const double pi=acos(-1.0); int n,m,limit=1,s,pos[N]; struct node { double x,y; node (double xx=0,double yy=0) {x=xx;y=yy;} }a[N],b[N]; node operator + (node a,node b){return node(a.x+b.x,a.y+b.y);} node operator - (node a,node b){return node(a.x-b.x,a.y-b.y);} node operator * (node a,node b){return node(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} void FFT(node *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { node base(cos(pi/mid),opt*sin(pi/mid)); for(int len=mid<<1,i=0;i<limit;i+=len) { node w(1,0); for(int j=0;j<mid;++j,w=w*base) { node x=nw[i+j]; node y=nw[i+j+mid]*w; nw[i+j]=x+y; nw[i+j+mid]=x-y; } } } } int main() { n=read(); m=read(); for(int i=0;i<=n;++i) a[i].x=read(); for(int i=0;i<=m;++i) b[i].x=read(); while(limit<=n+m) limit<<=1,s++; for(int i=1;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); FFT(a,1); FFT(b,1); for(int i=0;i<limit;++i) a[i]=a[i]*b[i]; FFT(a,-1); for(int i=0;i<=n+m;++i) printf("%d ",(int)(a[i].x/limit+0.5)); return 0; }
NTT:
#include<bits/stdc++.h> #define ll long long using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int N=3000050; const int p=998244353; int n,m,limit=1,s; int pos[N],a[N],b[N]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void FNT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;++j,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } int main() { n=read(); m=read(); for(int i=0;i<=n;++i) a[i]=read(); for(int i=0;i<=m;++i) b[i]=read(); while(limit<=n+m) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); FNT(a,1); FNT(b,1); for(int i=0;i<limit;++i) a[i]=(ll)a[i]*b[i]%p; FNT(a,-1); int inv=ksm(limit,p-2); for(int i=0;i<=n+m;++i) printf("%d ",(ll)a[i]*inv%p); return 0; }
FWT:
#include<bits/stdc++.h> #define ll long long #define p 998244353 using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int n,inv; int a[1000050],b[1000050],c[1000050]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void FWTOR(int *nw,int opt) { for(int mid=1;mid<n;mid<<=1) for(int len=mid<<1,i=0;i<n;i+=len) for(int j=0;j<mid;++j) if(opt==1) nw[i+j+mid]=(nw[i+j]+nw[i+j+mid])%p; else nw[i+j+mid]=(nw[i+j+mid]-nw[i+j]+p)%p; } void FWTAND(int *nw,int opt) { for(int mid=1;mid<n;mid<<=1) for(int len=mid<<1,i=0;i<n;i+=len) for(int j=0;j<mid;++j) if(opt==1) nw[i+j]=(nw[i+j]+nw[i+j+mid])%p; else nw[i+j]=(nw[i+j]-nw[i+j+mid]+p)%p; } void FWTXOR(int *nw,int opt) { for(int mid=1;mid<n;mid<<=1) for(int len=mid<<1,i=0;i<n;i+=len) for(int j=0;j<mid;++j) { int x=nw[i+j]; int y=nw[i+j+mid]; if(opt==1) nw[i+j]=(x+y)%p,nw[i+j+mid]=(x-y+p)%p; else nw[i+j]=(ll)(x+y)*inv%p,nw[i+j+mid]=(ll)(x-y+p)*inv%p; } } int main() { n=1<<read(); inv=ksm(2,p-2); for(int i=0;i<n;++i) a[i]=read(); for(int i=0;i<n;++i) b[i]=read(); FWTOR(a,1); FWTOR(b,1); for(int i=0;i<n;++i) c[i]=(ll)a[i]*b[i]%p; FWTOR(a,-1); FWTOR(b,-1); FWTOR(c,-1); for(int i=0;i<n;++i) printf("%d ",c[i]); puts(" "); FWTAND(a,1); FWTAND(b,1); for(int i=0;i<n;++i) c[i]=(ll)a[i]*b[i]%p; FWTAND(a,-1); FWTAND(b,-1); FWTAND(c,-1); for(int i=0;i<n;++i) printf("%d ",c[i]); puts(" "); FWTXOR(a,1); FWTXOR(b,1); for(int i=0;i<n;++i) c[i]=(ll)a[i]*b[i]%p; FWTXOR(a,-1);FWTXOR(b,-1); FWTXOR(c,-1); for(int i=0;i<n;++i) printf("%d ",c[i]); puts(" "); return 0; }
多项式求逆:
#include<bits/stdc++.h> #define ll long long #define p 998244353 using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*f; } const int N=400050; int n,len,limit,s; int f[N],g[N],a[N],b[N]; int pos[N]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void NTT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;++j,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } int main() { n=read()-1; for(int i=0;i<=n;++i) f[i]=read(); limit=2; len=1; s=1; g[0]=ksm(f[0],p-2); while(len<=n) { limit<<=1; len<<=1; s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); for(int i=0;i<len;++i) a[i]=f[i],b[i]=g[i]; NTT(a,1); NTT(b,1); for(int i=0;i<limit;++i) a[i]=((ll)2*b[i]%p-(ll)a[i]*b[i]%p*b[i]%p+p)%p; NTT(a,-1); int inv=ksm(limit,p-2); for(int i=0;i<len;++i) g[i]=(ll)a[i]*inv%p; } for(int i=0;i<=n;++i) printf("%d ",g[i]); return 0; }
多项式开根(求逆,开根):
#include<bits/stdc++.h> #define ll long long #define p 998244353 using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48); ch=getchar();} return x*f; } int n,m,inv2; int limit,s,pos[400050]; int f[400050],g[400050],h[400050]; int a_[400050],b_[400050],c_[400050]; int a__[400050],b__[400050],c__[400050],d__[400050]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void fir(int len) { limit=1; s=0; while(limit<=len+len) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); } void NTT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;++j,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } void INV(int *A,int *B,int N) { int len=1; B[0]=ksm(A[0],p-2); while(len<=N) { len<<=1; fir(len-1); for(int i=0;i<limit;++i) a_[i]=b_[i]=0; for(int i=0;i<len;++i) a_[i]=A[i],b_[i]=B[i]; NTT(a_,1); NTT(b_,1); for(int i=0;i<limit;++i) c_[i]=((ll)2*b_[i]%p-(ll)a_[i]*b_[i]%p*b_[i]%p+p)%p; NTT(c_,-1); int inv=ksm(limit,p-2); for(int i=0;i<len;++i) B[i]=(ll)c_[i]*inv%p; } } void SQRT(int *A,int *B,int N) { int len=1; B[0]=1; while(len<=N) { len<<=1; fir(len-1); for(int i=0;i<limit;++i) a__[i]=b__[i]=c__[i]=0; for(int i=0;i<len;++i) a__[i]=A[i],b__[i]=B[i]; INV(b__,c__,len-1); NTT(a__,1); NTT(b__,1); NTT(c__,1); for(int i=0;i<limit;++i) d__[i]=(ll)((ll)a__[i]+(ll)b__[i]*b__[i]%p)%p*inv2%p*c__[i]%p; NTT(d__,-1); int inv=ksm(limit,p-2); for(int i=0;i<len;++i) B[i]=(ll)d__[i]*inv%p; } } int main() { n=read()-1; inv2=ksm(2,p-2); for(int i=0;i<=n;++i) f[i]=read(); SQRT(f,g,n); for(int i=0;i<=n;++i) printf("%d ",g[i]); return 0; }
多项式除法(求逆,除法,取模):
#include<bits/stdc++.h> #define ll long long #define p 998244353 using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48); ch=getchar();} return x*f; } const int N=2000050; int n,m,nm; int limit,s,pos[N]; int f[N],g[N],h[N]; int val[N],ans[N]; int a[N],b[N],c[N]; int _a[N],_b[N],_c[N]; int __a[N],__b[N],__c[N],__d[N]; void fir(int len) { limit=1;s=0; while(limit<=len) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); } int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void NTT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;j++,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } void MUL(int *A,int *B,int *C,int N,int M) { fir(N+M); for(int i=0;i<limit;++i) a[i]=b[i]=0; for(int i=0;i<=N;++i) a[i]=A[i]; for(int i=0;i<=M;++i) b[i]=B[i]; NTT(a,1); NTT(b,1); for(int i=0;i<limit;++i) c[i]=(ll)a[i]*b[i]%p; NTT(c,-1); int inv=ksm(limit,p-2); for(int i=0;i<=N+M;++i) C[i]=(ll)c[i]*inv%p; } void INV(int *A,int *B,int N) { int len=1; _c[0]=ksm(A[0],p-2); _c[1]=0; while(len<=N) { len<<=1; fir(len+len-1); for(int i=0;i<limit;++i) _a[i]=_b[i]=0; for(int i=0;i<len;++i) _a[i]=A[i],_b[i]=_c[i]; NTT(_a,1); NTT(_b,1); for(int i=0;i<limit;++i) _c[i]=((ll)_b[i]*2-(ll)_a[i]*_b[i]%p*_b[i]%p+p)%p; NTT(_c,-1); int inv=ksm(limit,p-2); for(int i=0;i<len;++i) _c[i]=(ll)_c[i]*inv%p; for(int i=len;i<limit;++i) _c[i]=0; } for(int i=0;i<=N;++i) B[i]=_c[i]; } void MOD(int *A,int *B,int *C,int N,int M) { fir(N+N); for(int i=0;i<limit;++i) __a[i]=__b[i]=0; for(int i=0;i<=N;++i) __a[i]=A[N-i]; for(int i=0;i<=M;++i) __b[i]=B[M-i]; INV(__b,__b,N-M); MUL(__a,__b,__c,N,N-M); reverse(__c,__c+N-M+1); for(int i=0;i<=N;++i) __a[i]=A[i]; for(int i=0;i<=M;++i) __b[i]=B[i]; for(int i=0;i<=N-M;++i) cout<<__c[i]<<" "; cout<<endl; MUL(__b,__c,__d,M,N-M); for(int i=0;i<M;++i) C[i]=(__a[i]-__d[i]+p)%p; for(int i=0;i<M;++i) cout<<C[i]<<" "; } int main() { n=read(); m=read(); for(int i=0;i<=n;++i) f[i]=read(); for(int i=0;i<=m;++i) g[i]=read(); MOD(f,g,h,n,m); return 0; }
多项式快速幂(对数,指数):
#include<bits/stdc++.h> #define ll long long #define p 998244353 using namespace std; const int N=400050; int read() { ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=((x<<3)+(x<<1)+(ch^48))%p; ch=getchar();}; return (int)x*f; } int n,m,inv2; int limit,s,pos[N]; int f[N],g[N],h[N]; int a[N],b[N],c[N]; int _a[N],_b[N],_c[N],_ans[N]; int __a[N],__b[N],__c[N]; int ___a[N],___b[N],___c[N],___d[N],___ans[N]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void fir(int len) { limit=1; s=0; while(limit<=len) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); } void NTT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;++j,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } void DIREV(int *A,int *B,int N) { for(int i=0;i<N;++i) B[i]=(ll)A[i+1]*(i+1)%p; B[n]=0; } void INTER(int *A,int *B,int N) { for(int i=N;i>=1;--i) B[i]=(ll)A[i-1]*ksm(i,p-2)%p; B[0]=0; } void MUL(int *A,int *B,int *C,int N) { fir(N+N); for(int i=0;i<limit;++i) a[i]=b[i]=0; for(int i=0;i<=N;++i) a[i]=A[i],b[i]=B[i]; NTT(a,1); NTT(b,1); for(int i=0;i<limit;++i) c[i]=(ll)a[i]*b[i]%p; NTT(c,-1); int inv=ksm(limit,p-2); for(int i=0;i<=N+N;++i) C[i]=(ll)c[i]*inv%p; } void INV(int *A,int *B,int N) { int len=1; _ans[0]=ksm(A[0],p-2); _ans[1]=0; while(len<=N) { len<<=1; fir(len+len-1); for(int i=0;i<limit;++i) _a[i]=_b[i]=0; for(int i=0;i<len;++i) _a[i]=A[i],_b[i]=_ans[i]; NTT(_a,1); NTT(_b,1); for(int i=0;i<limit;++i) _c[i]=((ll)2*_b[i]%p-(ll)_a[i]*_b[i]%p*_b[i]%p+p)%p; NTT(_c,-1); int inv=ksm(limit,p-2); for(int i=0;i<len;++i) _ans[i]=(ll)_c[i]*inv%p; for(int i=len;i<limit;++i) _ans[i]=0; } for(int i=0;i<=N;++i) B[i]=_ans[i]; } void LN(int *A,int *B,int N) { for(int i=0;i<=N;++i) __a[i]=A[i]; INV(__a,__b,N); DIREV(__a,__c,N); MUL(__b,__c,__a,N); INTER(__a,__a,N); for(int i=0;i<=N;++i) B[i]=__a[i]; } void EXP(int *A,int *B,int N) { int len=1; ___ans[0]=1; ___ans[1]=0; while(len<=N) { len<<=1; LN(___ans,___a,len-1); ___a[0]=(___a[0]-1+p)%p; for(int i=0;i<len;++i) ___a[i]=(p-___a[i]+A[i])%p; MUL(___ans,___a,___ans,len-1); for(int i=len;i<limit;++i) ___ans[i]=0; } for(int i=0;i<=N;++i) B[i]=___ans[i]; } int main() { n=read()-1; m=read(); for(int i=0;i<=n;++i) f[i]=read(); LN(f,f,n); for(int i=0;i<=n;++i) f[i]=(ll)m*f[i]%p; EXP(f,f,n); for(int i=0;i<=n;++i) printf("%d ",f[i]); return 0; }
多项式多点求值:
#include<bits/stdc++.h> #define ll long long #define p 998244353 using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48); ch=getchar();} return x*f; } const int N=4000050; int n,m,LIMIT,S,SUM; int limit,s,pos[N]; int val[N],ans[N]; int aa[N],ab[N],ac[N]; int ba[N],bb[N],bc[N]; int ca[N],cb[N],cc[N],cd[N]; int t[16][N],f[N],g[N],h[N],r[N]; int w[N],iw[N],inv[N]; int add(int x,int y){ return x+y>p? x+y-p:x+y;} int mul(int x,int y){ return (ll)x*y-(ll)x*y/p*p;} void fir(int len) { limit=1; s=0; while(limit<=len) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); } int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=mul(sum,u); v>>=1; u=mul(u,u); } return sum; } void NTT(int *nw,int *W) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=LIMIT/mid; for(int len=mid<<1,i=0;i<limit;i+=len) { int k=0; for(int j=0;j<mid;j++,k+=base) { int x=nw[i+j]; int y=mul(W[k],nw[i+j+mid]); nw[i+j]=add(x,y); nw[i+j+mid]=add(x,p-y); } } } } void MUL(int *A,int *B,int *C,int N,int M,int *a=aa,int *b=ab,int *c=ac) { fir(N+M); for(int i=0;i<limit;++i) a[i]=b[i]=0; for(int i=0;i<=N;++i) a[i]=A[i]; for(int i=0;i<=M;++i) b[i]=B[i]; NTT(a,w); NTT(b,w); for(int i=0;i<limit;++i) c[i]=mul(a[i],b[i]); NTT(c,iw); for(int i=0;i<=N+M;++i) C[i]=mul(c[i],inv[s]); } void INV(int *A,int *B,int N,int *a=ba,int *b=bb,int *c=bc) { int len=1; c[0]=ksm(A[0],p-2); c[1]=0; while(len<=N) { len<<=1; fir(len); for(int i=0;i<limit;++i) a[i]=b[i]=0; for(int i=0;i<len;++i) a[i]=A[i],b[i]=c[i]; NTT(a,w); NTT(b,w); for(int i=0;i<limit;++i) c[i]=add(mul(b[i],2),p-mul(a[i],mul(b[i],b[i]))); NTT(c,iw); for(int i=0;i<len;++i) c[i]=mul(c[i],inv[s]);; for(int i=len;i<limit;++i) c[i]=0; } for(int i=0;i<=N;++i) B[i]=c[i]; } void MOD(int *A,int *B,int *C,int N,int M,int *a=ca,int *b=cb,int *c=cc,int *d=cd) { fir(N+N); for(int i=0;i<limit;++i) a[i]=b[i]=0; for(int i=0;i<=N;++i) a[i]=A[N-i]; for(int i=0;i<=M;++i) b[i]=B[M-i]; INV(b,b,N-M); MUL(a,b,c,N,N-M); reverse(c,c+N-M+1); for(int i=0;i<=N;++i) a[i]=A[i]; for(int i=0;i<=M;++i) b[i]=B[i]; MUL(b,c,d,M,N-M); for(int i=0;i<M;++i) C[i]=add(a[i],p-d[i]); } void calc() { w[0]=iw[0]=1; fir(n+n); LIMIT=limit>>1; S=s-1; for(int i=1;i<limit;++i) w[i]=ksm(3,(p-1)/limit*i); for(int i=1;i<limit;++i) iw[i]=ksm(w[i],p-2); for(int i=0;i<=s;++i) inv[i]=ksm(1<<i,p-2); for(int i=0;i<LIMIT;++i) t[0][i]=p-1; for(int mid=1,lg=0;mid<LIMIT/2;mid<<=1,lg++) { for(int len=mid<<1,i=0;i<LIMIT;i+=len) { f[0]=g[0]=1; for(int j=0;j<mid;++j) f[j+1]=t[lg][i+j]; for(int j=0;j<mid;++j) g[j+1]=t[lg][i+j+mid]; for(int j=0;j<mid;++j) f[0]=mul(f[0],val[i+j]); for(int j=0;j<mid;++j) g[0]=mul(g[0],val[i+j+mid]); MUL(f,g,h,mid,mid); for(int j=0;j<len;++j) t[lg+1][i+j]=h[j+1]; } } } void solve() { for(int mid=LIMIT/2,lg=S-1;mid>=1;mid>>=1,lg--) for(int len=mid<<1,i=0;i<LIMIT;i+=len) { f[0]=g[0]=1; for(int j=0;j<len;++j) h[j]=ans[i+j]; for(int j=0;j<mid;++j) f[j+1]=t[lg][i+j]; for(int j=0;j<mid;++j) g[j+1]=t[lg][i+j+mid]; for(int j=0;j<mid;++j) f[0]=mul(f[0],val[i+j]); for(int j=0;j<mid;++j) g[0]=mul(g[0],val[i+j+mid]); MOD(h,f,r,len-1,mid); for(int j=0;j<mid;++j) ans[i+j]=r[j]; MOD(h,g,r,len-1,mid); for(int j=0;j<mid;++j) ans[i+j+mid]=r[j]; } } int main() { n=read(); m=read(); for(int i=0;i<=n;++i) ans[i]=read(); for(int i=1;i<=m;++i) val[i]=read(); calc(); solve(); for(int i=1;i<=m;++i) printf("%d ",ans[i]); return 0; }
字符串算法:
后缀数组:
#include<bits/stdc++.h> using namespace std; int n,m; char s[1000050]; int height[2000050]; int sa[2000050],sb[2000050]; int rk[2000050],t[2000050],tot,top; void qsort() { for(int i=0;i<=m;i++) t[i]=0; for(int i=1;i<=n;i++) t[rk[i]]++; for(int i=1;i<=m;++i) t[i]+=t[i-1]; for(int i=n;i>=1;--i) sa[t[rk[sb[i]]]--]=sb[i]; } void calc_sa() { for(int i=1;i<=n;++i) sb[i]=i; for(int i=1;i<=n;++i) rk[i]=s[i]; for(int i=1;i<=n;++i) m=max(m,rk[i]); qsort(); for(int k=1;tot<n;k<<=1) { tot=top=0; for(int i=1;i<=k;++i) sb[++top]=n-k+i; for(int i=1;i<=n;++i) if(sa[i]>k) sb[++top]=sa[i]-k; qsort(); swap(rk,sb); rk[sa[1]]=++tot; for(int i=2;i<=n;++i) { if(sb[sa[i]]!=sb[sa[i-1]]||sb[sa[i]+k]!=sb[sa[i-1]+k]) ++tot; rk[sa[i]]=tot; } m=tot; } } void calc_height() { for(int i=1,j,k=0;i<=n;++i) { j=sa[rk[i]-1]; if(k) --k; while(s[i+k]==s[j+k]) ++k; height[rk[i]]=k; } } int main() { scanf("%s",s+1); n=strlen(s+1); calc_sa(); calc_height(); for(int i=1;i<=n;++i) printf("%d ",sa[i]); puts(" "); for(int i=1;i<=n;++i) printf("%d ",height[i]); return 0; }
数论:
第一类斯特林数(行):
#include<bits/stdc++.h> #define ll long long #define p 167772161 using namespace std; int n,limit,s; int fac[1000050]; int fav[1000050]; int tmp[1000050]; int pos[1000050]; int ans[1000050]; int a[1000050]; int b[1000050]; int c[1000050]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void fir(int len) { limit=1; s=0; while(limit<=(len<<1)) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); } void NTT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;j++,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } void mul(int *A,int *B,int *C,int len) { for(int i=len+1;i<limit;++i) A[i]=B[i]=0; NTT(A,1); NTT(B,1); for(int i=0;i<limit;++i) C[i]=(ll)A[i]*B[i]%p; NTT(C,-1); int INV=ksm(limit,p-2); for(int i=0;i<limit;++i) C[i]=(ll)C[i]*INV%p; } void solve(int LEN) { if(LEN<=1) { ans[LEN]=1; return ;} solve(LEN>>1); int len=LEN>>1; fir(len); for(int i=1;i<=len;++i) tmp[i]=(ll)tmp[i-1]*len%p; for(int i=0;i<=len;++i) a[i]=(ll)tmp[i]*fav[i]%p; for(int i=0;i<=len;++i) b[i]=(ll)ans[i]*fac[i]%p; for(int i=0;i<=(len>>1);++i) swap(b[i],b[len-i]); mul(a,b,c,len); for(int i=0;i<=len;++i) a[i]=(ll)c[len-i]*fav[i]%p; for(int i=0;i<=len;++i) b[i]=ans[i]; mul(a,b,c,len); for(int i=0;i<=LEN;++i) ans[i]=c[i]; if(LEN&1) for(int i=1;i<=LEN;++i) ans[i]=((ll)c[i]*(LEN-1)%p+c[i-1])%p; } int main() { scanf("%d",&n); fac[0]=fac[1]=fav[0]=fav[1]=tmp[0]=1; for(int i=1;i<=n;++i) fac[i]=(ll)fac[i-1]*i%p; for(int i=2;i<=n;++i) fav[i]=p-(ll)p/i*fav[p%i]%p; for(int i=1;i<=n;++i) fav[i]=(ll)fav[i-1]*fav[i]%p; solve(n); for(int i=0;i<=n;++i) printf("%d ",ans[i]); return 0; }
第二类斯特林数(行):
#include<bits/stdc++.h> #define ll long long #define p 167772161 using namespace std; int n,limit,s; int fac[1000050]; int fav[1000050]; int pos[1000050]; int ans[1000050]; int a[1000050]; int b[1000050]; int ksm(int u,int v) { int sum=1; while(v) { if(v&1) sum=(ll)sum*u%p; v>>=1; u=(ll)u*u%p; } return sum; } void calc(int len) { limit=1; s=0; while(limit<=(len<<1)) limit<<=1,s++; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1)); } void NTT(int *nw,int opt) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(nw[i],nw[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int base=ksm(3,(p-1)/(mid<<1)); if(opt==-1) base=ksm(base,p-2); for(int len=mid<<1,i=0;i<limit;i+=len) { int w=1; for(int j=0;j<mid;j++,w=(ll)w*base%p) { int x=nw[i+j]; int y=(ll)w*nw[i+j+mid]%p; nw[i+j]=(x+y)%p; nw[i+j+mid]=(x-y+p)%p; } } } } void mul(int *A,int *B,int *C,int len) { for(int i=len+1;i<limit;++i) A[i]=B[i]=0; NTT(A,1); NTT(B,1); for(int i=0;i<limit;++i) C[i]=(ll)A[i]*B[i]%p; NTT(C,-1); int INV=ksm(limit,p-2); for(int i=0;i<limit;++i) C[i]=(ll)C[i]*INV%p; } int main() { scanf("%d",&n); fac[0]=fac[1]=fav[0]=fav[1]=1; for(int i=1;i<=n;++i) fac[i]=(ll)fac[i-1]*i%p; for(int i=2;i<=n;++i) fav[i]=p-(ll)p/i*fav[p%i]%p; for(int i=1;i<=n;++i) fav[i]=(ll)fav[i-1]*fav[i]%p; for(int i=0;i<=n;++i) a[i]=(i&1)? -fav[i]:fav[i]; for(int i=0;i<=n;++i) b[i]=(ll)ksm(i,n)*fav[i]%p; calc(n); mul(a,b,ans,n); for(int i=0;i<=n;++i) printf("%d ",ans[i]); return 0; }
网络流:
求解一组最小割边:
#include<bits/stdc++.h> #define INF 1<<30 using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48); ch=getchar();} return x*f; } queue<int >q; int dis[100050]; bool vis[100050]; int n,m,s,t,tot=1,x,y,z,ans; int head[100050],nex[100050],ver[100050],flow[100050]; void add(int x,int y,int z) { ++tot;nex[tot]=head[x];head[x]=tot;ver[tot]=y;flow[tot]=z; ++tot;nex[tot]=head[y];head[y]=tot;ver[tot]=x;flow[tot]=0; } bool bfs() { memset(dis,0,sizeof(dis)); q.push(s); dis[s]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=nex[i]) { int v=ver[i]; if(!dis[v]&&flow[i]) { dis[v]=dis[u]+1; if(v!=t) q.push(v); } } } return dis[t]; } int dfs(int u,int FLOW) { if(u==t) return FLOW; int VAL=0; for(int i=head[u];i;i=nex[i]) { int v=ver[i]; if(dis[v]==dis[u]+1&&flow[i]) { int tmp=dfs(v,min(FLOW,flow[i])); flow[i]-=tmp; flow[i^1]+=tmp; VAL+=tmp; FLOW-=tmp; if(!tmp) dis[v]=0; if(!FLOW) break; } } return VAL; } void calc() { q.push(s); vis[s]=true; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=nex[i]) { int v=ver[i]; if(!flow[i]) continue; if(!vis[v]) { q.push(v); vis[v]=true; } } } } int main() { n=read(); m=read(); s=read(); t=read()+n; for(int i=1;i<=n;++i) add(i,i+n,read()); for(int i=1;i<=m;++i) { x=read(); y=read(); add(x+n,y,INF); add(y+n,x,INF); } while(bfs()) ans+=dfs(s,INF); calc(); for(int i=1;i<=n;++i) if(vis[i]&&!vis[i+n]) printf("%d ",i); return 0; }
求解可行边与必须边:
#include<bits/stdc++.h> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x*f; } int n,m,x,y,z,S,T; int dfn[10050],low[10050],t[10050],top,cnt,col[10050],sum; int head[10050],nex[120050],ver[120050],flow[120050],tot=1; int dis[10050]; queue<int >q; bool bfs() { memset(dis,0,sizeof(dis)); q.push(S); dis[S]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=nex[i]) { int v=ver[i]; if(!dis[v]&&flow[i]) { dis[v]=dis[u]+1; if(v!=T) q.push(v); } } } return dis[T]; } int dfs(int u,int FLOW) { if(u==T) return FLOW; int VAL=0; for(int i=head[u];i;i=nex[i]) { int v=ver[i]; if(dis[v]==dis[u]+1&&flow[i]) { int tmp=dfs(v,min(FLOW,flow[i])); if(!tmp) dis[v]=0; flow[i]-=tmp; flow[i^1]+=tmp; VAL+=tmp; FLOW-=tmp; if(!FLOW) break; } } return VAL; } void tarjan(int u) { dfn[u]=low[u]=++cnt; t[++top]=u; for(int i=head[u];i;i=nex[i]) { if(!flow[i]) continue; int v=ver[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(!col[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { ++sum; while(t[top+1]!=u) col[t[top--]]=sum; } } int main() { n=read(); m=read(); S=read(); T=read(); for(int i=1;i<=m;++i) { x=read(); y=read(); z=read(); ++tot;nex[tot]=head[x];head[x]=tot;ver[tot]=y;flow[tot]=z; ++tot;nex[tot]=head[y];head[y]=tot;ver[tot]=x;flow[tot]=0; } while(bfs()) dfs(S,1<<30); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=2;i<=tot;i+=2) if(!flow[i]) { if(col[ver[i]]!=col[ver[i^1]]) printf("1 "); else printf("0 "); if(col[S]==col[ver[i^1]]&&col[ver[i]]==col[T]) printf("1 "); else printf("0 "); } else printf("0 0 "); return 0; }