【模板】多项式求逆

问题描述

P4328

给定一个多项式 $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

原文地址:https://www.cnblogs.com/lfri/p/11234854.html