http://172.20.6.3/Problem_Show.asp?id=2042
题意:求一个次数界为n的多项式在模P并模x^m的意义下的逆元。P=7*17*2^23+1。
多项式逆元的含义以及求逆元的方法:http://blog.miskcoo.com/2015/05/polynomial-inverse
公式推导一下。主要还是NTT的使用,我NTT写错了调了半天,太zz了。
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 LL P=(LL)7*17*(1<<23)+1; 10 const int maxn=530010; 11 LL a[maxn]={},b[maxn]={},e[maxn]={},zz[20][maxn]={}; 12 int bel[maxn]={}; 13 int bt,s,tot=0; 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; 20 k/=2; 21 }return z; 22 } 23 inline void getit(){ for(int i=0;i<s;i++)bel[i]=((bel[i>>1]>>1)|((i&1)<<(bt-1))); } 24 inline void ntt(LL *c,int n,int dft){ 25 for(int i=0;i<n;i++)if(bel[i]>i)swap(c[bel[i]],c[i]); 26 for(int step=1;step<n;step<<=1){ 27 LL w=mpow(3,((P-1)/(step*2))*dft); 28 for(int j=0;j<n;j+=(step<<1)){ 29 LL z=1; 30 for(int i=j;i<j+step;++i){ 31 LL x=c[i],y=(c[i+step]*z)%P; 32 c[i]=(x+y)%P; 33 c[i+step]=((x-y)%P+P)%P; 34 z=(z*w)%P; 35 } 36 } 37 } 38 if(dft==-1){ 39 LL mon=mpow(n,P-2); 40 for(int i=0;i<n;i++)c[i]=(c[i]*mon)%P; 41 } 42 } 43 inline void dontt(LL *c,LL *d,int x,int y){ 44 bt=1;s=2;int z=x+y-1; 45 for(;s<z;++bt)s<<=1; 46 getit(); 47 ntt(c,s,1);ntt(d,s,1); 48 for(int i=0;i<s;i++)c[i]=(c[i]*d[i])%P; 49 ntt(c,s,-1);ntt(d,s,1); 50 } 51 inline void doit(int n,int m){ 52 if(m==1){++tot; zz[tot][0]=mpow(a[0],P-2); return ;} 53 doit(n,(m+1)/2);int siz=(m+1)/2; ++tot; 54 for(int i=0;i<s;i++)e[i]=b[i]=bel[i]=0; 55 for(int i=0;i<siz;i++){zz[tot][i]=(zz[tot-1][i]*2)%P;b[i]=zz[tot-1][i];} 56 for(int i=min(n,m)-1;i>=0;--i)e[i]=a[i]; 57 dontt(zz[tot-1],b,siz,siz); siz=siz+siz-1; 58 dontt(zz[tot-1],e,siz,min(n,m)); 59 for(int i=0;i<m;i++)zz[tot][i]=((zz[tot][i]-zz[tot-1][i])%P+P)%P; 60 } 61 int main(){ 62 //freopen("a.in","r",stdin); 63 int n,m;scanf("%d%d",&n,&m); 64 for(int i=0;i<n;i++){scanf("%lld",&a[i]);a[i]=((a[i]%P)+P)%P;} 65 doit(n,m); 66 for(int i=0;i<m;i++)printf("%lld ",zz[tot][i]); 67 printf(" "); 68 return 0; 69 }