zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    初认识AngularJS
    (imcomplete) UVa 10127 Ones
    UVa 10061 How many zero's and how many digits?
    UVa 11728 Alternate Task
    UVa 11490 Just Another Problem
    UVa 10673 Play with Floor and Ceil
    JSON对象和字符串的收发(JS客户端用typeof()进行判断非常重要)
    HTML.ActionLink 和 Url.Action 的区别
    EASYUI TREE得到当前节点数据的GETDATA方法
    jqueery easyui tree把已选中的节点数据拼成json或者数组(非常重要)
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10566972.html
Copyright © 2011-2022 走看看