多项式求逆
先存一套模板,有个细节没搞懂。待更。
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<algorithm> #include<cmath> #define M 263000 using namespace std; typedef long long ll; ll wn[100];//,P=1004535809; ll P=17ll*(1<<27)+1; int n,m,G=3; ll mod_pow(ll x,ll n,ll p){ ll res=1; while(n){ if(n&1) res=res*x%p; x=x*x%p; n>>=1; } return res; } void getwn(){ for(int i=0;i<27;i++) wn[i]=mod_pow(G,(P-1)/(1<<i),P); }//预处理w void NTT(ll x[],ll n,ll rev){ ll w,u,v; for(int i=0,j=0;i!=n;i++){//构造逆序表 if(i>j) swap(x[i],x[j]); for(int l=n>>1;(j^=l)<l;l>>=1); } for(int i=2,ds=1;i<n;i<<=1,ds++) for(int j=0;j<n;j+=i){ w=1; for(int k=j;k<j+i/2;k++,w=w*wn[ds]%P){//蝴蝶操作 u=x[k]%P;v=w*x[k+i/2]%P; x[k]=(u+v)%P; x[k+i/2]=(u-v+P)%P; } } if(rev==-1){ for(int i=1;i<n/2;i++) swap(x[i],x[n-i]); w=mod_pow(n,P-2,P);//乘n的逆元 for(int i=0;i<n;i++) x[i]=x[i]*w%P; } } // b是逆存放的位置 ll tmp[M]; void Get_Inv(ll a[],ll b[],ll n){ if(n==1){ b[0]=mod_pow(a[0],P-2,P); return; } Get_Inv(a,b,(n+1)>>1);//递归之后 ll p=1; while(p<(n<<1)) p<<=1; copy(a,a+n,tmp); fill(tmp+n,tmp+p,0); NTT(tmp,p,1); NTT(b,p,1); for(int i=0;i<p;i++) b[i]=b[i]*(2-tmp[i]*b[i]%P+P)%P; NTT(b,p,-1); fill(b+n,b+p,0); } ll a[3000],b[3000]; int main(){ getwn(); int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lld",&a[i]); Get_Inv(a,b,n); for(int i=0;i<n;i++) printf("%lld ",b[i]); }