P4238 【模板】多项式求逆

思路

多项式求逆就是对于一个多项式(A(x)),求一个多项式(B(x)),使得(A(x)B(x) equiv 1 (mod x^n))

假设现在多项式只有一项,显然(B(x))的第0项(常数项)就是(A(x))的第0项(常数项)的逆元(所以(A(x))有没有逆元取决于(A(x))的常数项有没有逆元)

那我们可以利用递归的方法,

现在要求

[A(x)B(x) equiv 1 (mod x^n) ]

假设有多项式(B'(x)),满足

[A(x)B'(x)equiv 1 (mod x^{lfloorfrac{n}{2} floor}) ]

则要求的(B(x)),必定也满足

[A(x)B(x) equiv 1 (mod x^{lfloorfrac{n}{2} floor}) ]

所以有

[A(x)(B(x)-B'(x)) equiv 0 (mod x^{lfloorfrac{n}{2} floor})\B(x)-B'(x)equiv 0 (mod x^{lfloorfrac{n}{2} floor})\ (B(x)-B'(x))^2equiv 0 (mod x^{n})\ B^2(x)-2B(x)B'(x)+B'^2(x)equiv 0 (mod x^{n})\ ]

两侧都乘(A(x))

[B(x)-2B'(x)+2A(x)B'^2(x)equiv 0 (mod x^n) ]

所以

[B(x)equiv B'(x)(2-A(x)B'(x)) ]

递归求解即可

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int MOD = 998244353,G = 3, invG = 332748118;
int pow(int a,int b){
    int ans=1;
    while(b){
        if(b&1)
            ans=(a*ans)%MOD;
        a=(a*a)%MOD;
        b>>=1;
    }
    return ans;
}
void NTT(int *a,int n,int opt){
    int lim=0;
    while((1<<lim)<n)
        lim++;
    n=(1<<lim);
    for(int i=0;i<n;i++){
        int t=0;
        for(int j=0;j<lim;j++)
            if((i>>j)&1)
                t|=(1<<(lim-j-1));
        if(t<i)
            swap(a[t],a[i]);
    }
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        int tmp=pow((opt)?G:invG,(MOD-1)/i);
        for(int j=0;j<n;j+=i){
            int mid=1;
            for(int k=j;k<j+len;k++){
                int t=a[k+len]*mid;
                a[k+len]=(a[k]-t+MOD)%MOD;
                a[k]=(a[k]+t)%MOD;
                mid=(mid*tmp)%MOD;
            }
        }
    }
    if(!opt){
        int invn=pow(n,MOD-2);
        for(int i=0;i<n;i++)
            a[i]=(a[i]*invn)%MOD;
    }
}
int c[300100],a[300100],b[300100],n;
void get_inv(int times,int *a,int *b){
    if(times==1){
        b[0]=pow(a[0],MOD-2);
        return;
    }
    get_inv((times+1)>>1,a,b);
    while((times<<1)>n)
        n<<=1;
    for(int i=0;i<times;i++){
        c[i]=a[i];
    }
    for(int i=times;i<n;i++){
        c[i]=0;
    }
    NTT(c,n,1);
    NTT(b,n,1);
    for(int i=0;i<n;i++){
        b[i]=((2-c[i]*b[i]%MOD)%MOD+MOD)%MOD*b[i]%MOD;
    }
    NTT(b,n,0);
    for(int i=times;i<n;i++){
        b[i]=0;
    }
}
signed main(){
    scanf("%lld",&n);
    int tx=n;
    for(int i=0;i<tx;i++)
        scanf("%lld",&a[i]);
    n=1;
    get_inv(tx,a,b);
    for(int i=0;i<tx;i++){
        printf("%lld ",(b[i]+MOD)%MOD);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dreagonm/p/10566972.html