多项式求逆

先存一套模板,有个细节没搞懂。待更。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define M 263000
using namespace std;
typedef long long ll;
ll wn[100];//,P=1004535809;
ll P=17ll*(1<<27)+1;
int n,m,G=3;
ll mod_pow(ll x,ll n,ll p){
    ll res=1;
    while(n){
        if(n&1) res=res*x%p;
        x=x*x%p;
        n>>=1;
    }
    return res;
}
void getwn(){ 
    for(int i=0;i<27;i++) 
        wn[i]=mod_pow(G,(P-1)/(1<<i),P);
}//预处理w
void NTT(ll x[],ll n,ll rev){
    ll w,u,v;
    for(int i=0,j=0;i!=n;i++){//构造逆序表
        if(i>j) swap(x[i],x[j]);
        for(int l=n>>1;(j^=l)<l;l>>=1);
    }
    for(int i=2,ds=1;i<n;i<<=1,ds++)
        for(int j=0;j<n;j+=i){
            w=1;
            for(int k=j;k<j+i/2;k++,w=w*wn[ds]%P){//蝴蝶操作
                u=x[k]%P;v=w*x[k+i/2]%P;
                x[k]=(u+v)%P;
                x[k+i/2]=(u-v+P)%P;
            }
        }
    if(rev==-1){
        for(int i=1;i<n/2;i++) swap(x[i],x[n-i]);
        w=mod_pow(n,P-2,P);//乘n的逆元
        for(int i=0;i<n;i++) x[i]=x[i]*w%P;
    }
}

// b是逆存放的位置 
ll tmp[M];
void Get_Inv(ll a[],ll b[],ll n){
    if(n==1){
        b[0]=mod_pow(a[0],P-2,P);
        return;
    }
    Get_Inv(a,b,(n+1)>>1);//递归之后 
    ll p=1;
    while(p<(n<<1)) p<<=1;
    copy(a,a+n,tmp);
    fill(tmp+n,tmp+p,0);
    NTT(tmp,p,1);
    NTT(b,p,1);
    for(int i=0;i<p;i++) b[i]=b[i]*(2-tmp[i]*b[i]%P+P)%P;
    NTT(b,p,-1);
    fill(b+n,b+p,0);
}

ll a[3000],b[3000];
int main(){
    getwn();
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%lld",&a[i]);
    Get_Inv(a,b,n);
    for(int i=0;i<n;i++) printf("%lld ",b[i]);
}
原文地址:https://www.cnblogs.com/elpsycongroo/p/7885441.html