模板多项式求逆
Posted lfri
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板多项式求逆相关的知识,希望对你有一定的参考价值。
问题描述
给定一个多项式 $F(x)$,请求出一个多项式 $G(x)$,满足 $ F(x) * G(x) \\equiv 1(mod \\ x^n)$。系数对998244353998244353取模。
分析
理论基础
这是一个递推式且呈平方倍增加,就可以用倍增求多项式逆元,从 $x^1$ 开始推至 $x^2^m(2^m \\geq n)$即可。初值 $B = A(0)^-1$。
利用NTT可以将多项式乘法优化至 $nlog_2n$,利用主定理计算得总时间复杂度为 $O(nlog_2n)$。
代码:
#include<bits/stdc++.h> using namespace std; int read() int q=0;char ch=‘ ‘; while(ch<‘0‘||ch>‘9‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) q=q*10+ch-‘0‘,ch=getchar(); return q; #define RI register int typedef long long ll; const int mod=998244353,G=3,N=4*100000 + 10; //同NTT,需要4倍的空间 int n; int a[N],b[N],c[N],rev[N]; inline int qpow(int x,int k) int ans=1; while(k) if(k&1) ans=(ll)ans*x%mod; x=(ll)x*x%mod,k>>=1; return ans; void NTT(int *a,int n,int x) for(RI i=0;i<n;++i) if(i<rev[i]) swap(a[i],a[rev[i]]); for(RI i=1;i<n;i<<=1) RI gn=qpow(G,(mod-1)/(i<<1)); for(RI j=0;j<n;j+=(i<<1)) RI t1,t2,g=1; for(RI k=0;k<i;++k,g=1LL*g*gn%mod) t1=a[j+k],t2=1LL*g*a[j+k+i]%mod; a[j+k]=(t1+t2)%mod,a[j+k+i]=(t1-t2+mod)%mod; if(x==1) return; int ny=qpow(n,mod-2); reverse(a+1,a+n); for(RI i=0;i<n;++i) a[i]=1LL*a[i]*ny%mod; void work(int deg,int *a,int *b) if(deg==1) b[0]=qpow(a[0],mod-2);return; work((deg+1)>>1,a,b); RI len=0,orz=1; while(orz<(deg<<1)) orz<<=1,++len; for(RI i=1;i<orz;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1)); for(RI i=0;i<deg;++i) c[i]=a[i]; //C=A for(RI i=deg;i<orz;++i) c[i]=0; NTT(c,orz,1),NTT(b,orz,1); for(RI i=0;i<orz;++i) b[i]=1LL*(2-1LL*c[i]*b[i]%mod+mod)%mod*b[i]%mod; //B = 2B-2CB^2 = (2-CB)B NTT(b,orz,-1); for(RI i=deg;i<orz;++i) b[i]=0; int main() n=read(); for(RI i=0;i<n;++i) a[i]=read(); work(n,a,b); for(RI i=0;i<n;++i) printf("%d ",b[i]); return 0;
参考链接:https://www.luogu.org/problemnew/solution/P4238
以上是关于模板多项式求逆的主要内容,如果未能解决你的问题,请参考以下文章