http://blog.miskcoo.com/2015/05/polynomial-division 好神啊!
通过翻转多项式消除余数的影响,主要原理是商只与次数不小于m的项有关。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 550000 #define P 998244353 int n,m,t,a[N],b[N],r[N],c[N],d[N],e[N],inv3; int ksm(int a,int k) { if (k==0) return 1; int tmp=ksm(a,k>>1); if (k&1) return 1ll*tmp*tmp%P*a%P; else return 1ll*tmp*tmp%P; } int inv(int a){return ksm(a,P-2);} void DFT(int n,int *a,int p) { for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]); for (int i=2;i<=n;i<<=1) { int wn=ksm(p,(P-1)/i); for (int j=0;j<n;j+=i) { int w=1; for (int k=j;k<j+(i>>1);k++,w=1ll*w*wn%P) { int x=a[k],y=1ll*w*a[k+(i>>1)]%P; a[k]=(x+y)%P,a[k+(i>>1)]=(x-y+P)%P; } } } } void mul(int n,int *a,int *b) { DFT(n,a,3),DFT(n,b,3); for (int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%P; DFT(n,a,inv3); int invn=inv(n); for (int i=0;i<n;i++) a[i]=1ll*a[i]*invn%P; } int main() { #ifndef ONLINE_JUDGE freopen("division.in","r",stdin); freopen("division.out","w",stdout); const char LL[]="%I64d"; #else const char LL[]="%lld"; #endif n=read(),m=read(); for (int i=0;i<=n;i++) a[i]=read(); for (int i=0;i<=m;i++) b[i]=read(); reverse(b,b+m+1); t=1;c[0]=inv(b[0]); inv3=inv(3); while (t<n-m+1) { t<<=1; for (int i=0;i<t;i++) d[i]=b[i]; t<<=1; for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1); memcpy(e,c,sizeof(e)); mul(t,e,d); for (int i=0;i<t;i++) e[i]=(P-e[i])%P; e[0]=(e[0]+2)%P; for (int i=(t>>1);i<t;i++) e[i]=0; mul(t,c,e); for (int i=(t>>1);i<t;i++) c[i]=0; t>>=1; } memcpy(d,a,sizeof(a)); reverse(d,d+n+1); for (int i=n-m+1;i<=n;i++) c[i]=d[i]=0; t=1;while (t<=(n-m+1<<1)) t<<=1; for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1); mul(t,c,d); for (int i=n-m+1;i<t;i++) c[i]=0; reverse(c,c+n-m+1); for (int i=0;i<=n-m;i++) printf("%d ",c[i]);cout<<endl; reverse(b,b+m+1); t=1;while (t<=n) t<<=1; for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1); mul(t,c,b); for (int i=0;i<m;i++) printf("%d ",(a[i]-c[i]+P)%P); return 0; }