CAD快捷鍵設定在哪裡?CAD快捷鍵設定教程
阿新 • • 發佈:2021-12-21
多項式求逆元
已知一度數為n的多項式\(A(x)\)。
\[A(x)B(x)\equiv1\pmod {x^n} \]\(B(x)\)即為\(A(x)\)的逆元。
多項式的除法、\(\exp\)和\(\ln\)都是基於多項式求逆的。
通常用倍增法處理多項式求逆問題。
開始推式子……
\[\begin{aligned} &AB'\equiv1\pmod {x^{\lceil\frac n 2\rceil}}\\ &A(B-B’)\equiv 0 \pmod {x^{\lceil\frac n 2\rceil}}\\ &B-B’\equiv 0 \pmod {x^{\lceil\frac n 2\rceil}}\\ &(B-B’)^2\equiv 0 \pmod {x^n}\\ &B^2+B'^2-2BB'\equiv 0 \pmod {x^n}\\ &A(B^2+B'^2-2BB')\equiv 0 \pmod {x^n}\\ &B-2B'+AB'^2\equiv 0 \pmod {x^n}\\ &B\equiv 2B'-AB'^2\pmod {x^n}\\ &B\equiv B'(2-AB')\pmod {x^n}\\ \end{aligned} \]這樣我們可以從\(x^n\)
使用NTT加速運算,複雜度\(O(n \log n)\)。
ll qp(ll d,ll c) { ll res=1; while(c) { if(c&1) res=d*res%mod; d=d*d%mod,c>>=1; } return res; } void ntt(ll *a,int type) { for(int i=0;i<lim;i++) if(i<rev[i]) swap(a[i],a[rev[i]]); for(int mid=1;mid<lim;mid<<=1) { ll wn=qp(type?g:gi,(mod-1)/(mid<<1)); for(int i=0;i<lim;i+=(mid<<1)) { ll w=1; for(int j=0;j<mid;j++,w=w*wn%mod) { ll x=a[i+j],y=w*a[i+j+mid]%mod; a[i+j]=(x+y)%mod; a[i+j+mid]=(x-y+mod)%mod; } } } if(!type) { ll inv=qp(lim,mod-2); for(int i=0;i<lim;i++) a[i]=(a[i]*inv)%mod; } } void qn(ll deg,ll *a,ll *b) { if(deg==1) { b[0]=qp(a[0],mod-2); return; } qn((deg+1)/2,a,b); bit=0,lim=1; for(;lim<deg*2;lim*=2) bit++; for(int i=1;i<lim;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1)); for(int i=0;i<deg;i++) c[i]=a[i]; for(int i=deg;i<lim;i++) c[i]=0; ntt(c,1),ntt(b,1); for(int i=0;i<lim;i++) b[i]=(2-c[i]*b[i]%mod+mod)%mod*b[i]%mod; ntt(b,0); for(int i=deg;i<lim;i++) b[i]=0; }