[多项式求逆]多项式求逆模板
#include <iostream> #include <cstdio> #include <cmath> #include <memory.h> using namespace std; typedef long long ll; const int N=524288; const ll P=998244353; int n,rev[N],mxb,bit; ll fake_a[N],fake_b[N],a[N],b[2][N]; void Get_Rev(int bit,int mxb) {for (int i=1;i<mxb;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<bit-1);} ll Pow(ll x,ll y) {ll ans=1;for (;y;y>>=1,(x*=x)%=P) (ans*=(y&1?x:1))%=P;return ans;} void NTT(ll *a,int n,int idft) { for (int i=1;i<=n;i++) if (rev[i]>i) swap(a[rev[i]],a[i]); for (int mlen=1;mlen<n;mlen<<=1) { ll g1=Pow(3,(P-1)/(mlen<<1)); if (idft<0) g1=Pow(g1,P-2); for (int l=0,len=mlen<<1;l<n;l+=len) { ll gk=1; for (int i=l;i<l+mlen;i++) { ll x=a[i],y=(a[i+mlen]*gk)%P; a[i]=(x+y)%P;a[i+mlen]=(x-y+P)%P; (gk*=g1)%=P; } } } if (idft<0) { ll inv=Pow(n,P-2); for (int i=0;i<n;i++) (a[i]*=inv)%=P; } } void Roll_Multi(ll *a,ll *b,int mxb) { memset(fake_a,0,sizeof fake_a); memset(fake_b,0,sizeof fake_b); int half=mxb>>1; for (int i=0;i<half;i++) fake_a[i]=a[i],fake_b[i]=b[i]; NTT(fake_a,mxb,1);NTT(fake_b,mxb,1); for (int i=0;i<mxb;i++) (fake_a[i]*=fake_b[i])%P; NTT(fake_a,mxb,-1); for (int i=0;i<mxb;i++) a[i]=fake_a[i]; } void Calc_Inv() { } int main() { scanf("%d",&n); for (int i=0;i<n;i++) scanf("%lld",&a[i]); int j=0,bit=1; b[j][0]=Pow(a[0],P-2); for (int mlen=1,len=2;mlen<(n<<1);mlen<<=1,len<<=1,j^=1,++bit) { memset(b[j^1],0,sizeof b[j^1]);Get_Rev(bit,len); for (int i=0;i<mlen;i++) b[j^1][i]=(b[j][i]<<1)%P; Roll_Multi(b[j],b[j],len); Roll_Multi(b[j],a,len); for (int i=0;i<mlen;i++) b[j^1][i]=(b[j^1][i]-b[j][i]+P)%P; } for (int i=0;i<n;i++) printf("%lld ",b[j][i]); }
码着,找时间写题解
在日渐沉没的世界里,我发现了你。