多项式全家桶
Posted jrf123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式全家桶相关的知识,希望对你有一定的参考价值。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define mod 998244353 using namespace std; int n,a[600100],b[600100],ina[600100],lna[600100],lnc[600100],sqa[600100],sqb[600100],exa[600100],exb[600100],poa[600100],pob[600100],pos[600100]; int read() { int aa=0,bb=1;char cc=getchar(); while(cc>‘9‘||cc<‘0‘){if(cc==‘-‘) bb=-1;cc=getchar();} while(cc>=‘0‘&&cc<=‘9‘){aa=(aa<<3)+(aa<<1)+(cc^‘0‘);cc=getchar();} return aa*bb; } int quick(int x,int p) { int as=1; while(p){ if(p&1) as=1ll*as*x%mod; x=1ll*x*x%mod;p>>=1; } return as; } void ntt(int *a,int len,int opt) { for(int i=0;i<len;i++) if(i<pos[i]) swap(a[i],a[pos[i]]); for(int i=1;i<len;i<<=1){ int step=i<<1,wn=quick(3,(mod-1)/step); for(int j=0;j<len;j+=step){ int w=1; for(int k=0;k<i;k++,w=1ll*w*wn%mod){ int x=a[j+k],y=1ll*a[j+k+i]*w%mod; a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod; } } } if(opt){ reverse(a+1,a+len);int inv=quick(len,mod-2); for(int i=0;i<len;i++) a[i]=1ll*a[i]*inv%mod; } } void getderiv(int n,int *a,int *b) { for(int i=1;i<n;i++) b[i-1]=1ll*a[i]*i%mod; b[n-1]=0; } void getinteg(int n,int *a,int *b) { for(int i=1;i<n;i++) b[i]=1ll*a[i-1]*quick(i,mod-2)%mod; b[0]=0; } void getinv(int n,int *a,int *b) { if(n==1){b[0]=quick(a[0],mod-2);return;} getinv((n+1)>>1,a,b); int lenth=1,bit=0; while(lenth<=n+n+n) lenth<<=1,bit++; for(int i=0;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1); for(int i=0;i<n;i++) ina[i]=a[i]; for(int i=n;i<lenth;i++) ina[i]=0; ntt(ina,lenth,0);ntt(b,lenth,0); for(int i=0;i<lenth;i++) b[i]=(2ll*b[i]%mod-1ll*ina[i]*b[i]%mod*b[i]%mod+mod)%mod; ntt(b,lenth,1); for(int i=n;i<lenth;i++) b[i]=0; } void getln(int n,int *a,int *b) { getderiv(n,a,lna); getinv(n,a,lnc); int lenth=1,bit=0; while(lenth<=n+n) lenth<<=1,bit++; for(int i=0;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1); ntt(lna,lenth,0);ntt(lnc,lenth,0); for(int i=0;i<lenth;i++) lna[i]=1ll*lna[i]*lnc[i]%mod; ntt(lna,lenth,1);getinteg(n,lna,b); for(int i=0;i<lenth;i++) lna[i]=0,lnc[i]=0; } void getsqrt(int n,int *a,int *b) { if(n==1){b[0]=1;return;} getsqrt((n+1)>>1,a,b); getinv(n,b,sqb); int lenth=1,bit=0; while(lenth<=n+n+n) lenth<<=1,bit++; for(int i=0;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1); for(int i=0;i<n;i++) sqa[i]=a[i]; for(int i=n;i<lenth;i++) sqa[i]=0; ntt(b,lenth,0);ntt(sqa,lenth,0);ntt(sqb,lenth,0);int inv=quick(2,mod-2); for(int i=0;i<lenth;i++) b[i]=(1ll*b[i]*b[i]%mod+sqa[i])%mod*sqb[i]%mod*inv%mod; ntt(b,lenth,1); for(int i=n;i<lenth;i++) b[i]=0; for(int i=0;i<lenth;i++) sqb[i]=0; } void getexp(int n,int *a,int *b) { if(n==1){b[0]=1;return;} getexp((n+1)>>1,a,b); getln(n,b,exb); int lenth=1,bit=0; while(lenth<=n+n) lenth<<=1,bit++; for(int i=1;i<lenth;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<bit-1); for(int i=0;i<n;i++) exb[i]=(a[i]-exb[i]+mod)%mod;exb[0]++; for(int i=n;i<lenth;i++) exb[i]=0; ntt(exb,lenth,0);ntt(b,lenth,0); for(int i=0;i<lenth;i++) b[i]=1ll*b[i]*exb[i]%mod; ntt(b,lenth,1); for(int i=n;i<lenth;i++) b[i]=0; } void getpow(int n,int *a,int *b,int k) { getln(n,a,poa); for(int i=0;i<n;i++) pob[i]=1ll*poa[i]*k%mod; getexp(n,pob,b); int lenth=1,bit=0; while(lenth<=n) lenth<<=1,bit++; for(int i=n;i<lenth;i++) b[i]=0; for(int i=0;i<lenth;i++) poa[i]=0,pob[i]=0; } int main() { n=read(); for(int i=0;i<n;i++) a[i]=read(); getsqrt(n,a,b); for(int i=0;i<n;i++) printf("%d ",b[i]); return 0; }
啥都不会只会板子(现在连板子都不会了
以上是关于多项式全家桶的主要内容,如果未能解决你的问题,请参考以下文章