JZYZOJ 2043 多项式除法和取余 NTT 多项式
http://172.20.6.3/Problem_Show.asp?id=2043
最开始用了FFT,交上去全tle和wa了(tle的比较多),测了一组数据发现求逆元的过程爆double了(毕竟系数的指数幂也是指数增长的,科学计数法也撑不住)。
然后问了出题人,发现出题人忘了给用来%的P(想用钢丝球刷出题人QnQ),所以其实是ntt,改完ntt加了个快读a了。
题解:http://blog.miskcoo.com/2015/05/polynomial-division
依然是推式子,系数反转求也是很神奇。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<complex> 7 using namespace std; 8 #define LL long long 9 const int maxn=530010; 10 const LL P=(LL)7*17*(1<<23)+1; 11 LL a[maxn],b[maxn],e[maxn],h[maxn],zz[20][maxn]; 12 int bel[maxn]={},s,bt,tot=0; 13 inline void getit(){ for(int i=0;i<s;++i)bel[i]=((bel[i>>1]>>1)|((i&1)<<(bt-1))); } 14 LL mpow(LL x,LL k){ 15 if(k<0){x=mpow(x,P-2);k=-k;} 16 LL z=1; 17 while(k){ 18 if(k&1)z=(z*x)%P; 19 x=(x*x)%P;k/=2; 20 } 21 return z; 22 } 23 inline void fft(LL * c,int n,int dft){ 24 for(int i=1;i<n;++i)if(bel[i]>i)swap(c[i],c[bel[i]]); 25 for(int step=1;step<n;step<<=1){ 26 LL w=mpow(3,((P-1)/(step<<1))*dft); 27 for(int j=0;j<n;j+=(step<<1)){ 28 LL z=1; 29 for(int i=j;i<j+step;++i){ 30 LL x=c[i],y=(c[i+step]*z)%P; 31 c[i]=(x+y)%P;c[i+step]=((x-y)%P+P)%P; 32 z=(z*w)%P; 33 } 34 } 35 } 36 if(dft==-1){ 37 LL nm=mpow(n,P-2); 38 for(int i=0;i<n;++i)c[i]=(c[i]*nm)%P; 39 } 40 } 41 void dofft(LL *c,LL *d,int x,int y){ 42 int n=x+y-1;s=2;bt=1; 43 for(;s<n;++bt)s<<=1;getit(); 44 fft(c,s,1);fft(d,s,1); 45 for(int i=0;i<s;++i)c[i]=(c[i]*d[i])%P; 46 fft(c,s,-1);fft(d,s,-1); 47 } 48 void doit(int n,int m){ 49 if(m==1){ ++tot; zz[tot][0]=mpow(b[0],P-2); return; } 50 int siz=(m+1)/2; doit(n,siz); ++tot; 51 for(int i=0;i<siz;++i){zz[tot][i]=(zz[tot-1][i]*2)%P;e[i]=zz[tot-1][i];} 52 for(int i=0;i<min(m,n);++i)h[i]=b[i];//cout<<zz[tot-1][0]<<m<<endl; 53 dofft(zz[tot-1],e,siz,siz);siz=siz+siz-1;//cout<<zz[tot-1][0]<<m<<endl; 54 dofft(zz[tot-1],h,siz,min(m,n)); 55 for(int i=0;i<m;++i)zz[tot][i]=((zz[tot][i]-zz[tot-1][i])%P+P)%P; 56 //for(int i=0;i<m;++i)cout<<zz[tot][i]<<' ';cout<<endl; 57 } 58 LL mread(){ 59 LL x=0,f=1; char ch=getchar(); 60 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 61 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 62 return x*f; 63 } 64 int main(){ 65 //freopen("a.in","r",stdin); 66 int n,m;scanf("%d%d",&n,&m); 67 for(int i=0;i<n;++i){a[n-i-1]=mread();a[n-i-1]=(a[n-i-1]%P+P)%P;} 68 for(int i=0;i<m;++i){b[m-i-1]=mread();b[m-i-1]=(b[m-i-1]%P+P)%P;} 69 doit(m,n-m+1); 70 dofft(zz[tot],a,n-m+1,n); 71 for(int i=n-m;i>=0;--i){printf("%lld ",zz[tot][i]);}printf("\n"); 72 for(int i=n-m+1;i<s;++i)zz[tot][i]=0; 73 for(int i=0;i<=n-m;++i){if(i>=n-m-i)break;swap(zz[tot][i],zz[tot][n-m-i]);} 74 for(int i=0;i<n;++i){if(i>=n-i-1)break;swap(a[i],a[n-i-1]);} 75 for(int i=0;i<m;++i){if(i>=m-i-1)break;swap(b[i],b[m-i-1]);} 76 dofft(b,zz[tot],m,n-m+1); 77 for(int i=0;i<m-1;++i){a[i]=((a[i]-b[i])%P+P)%P;} 78 for(int i=0;i<m-1;++i){printf("%lld ",a[i]);}printf("\n"); 79 return 0; 80 }