P4238 【模板】多项式求逆(多项式求逆模板)

P4238 【模板】多项式求逆

题意:

在这里插入图片描述
数据范围
1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1n105
1 ≤ a i ≤ 1 0 9 1\leq a_i\leq 10^9 1ai109

题解:

f ∗ g ≡ 1 ( m o d    x n ) f*g\equiv1(\mod x^n) fg1(modxn)
f ∗ a ≡ 1 ( m o d    x n 2 ) f*a\equiv1(\mod x^{\frac n 2}) fa1(modx2n)
g − a ≡ 0 ( m o d    x n 2 ) g-a\equiv0(\mod x^{\frac n 2}) ga0(modx2n)
( g − a ) 2 ≡ 0 ( m o d    x n ) (g-a)^2\equiv0(\mod x^n) (ga)20(modxn)
g 2 + a 2 − 2 a g ≡ 0 ( m o d    x n ) g^2+a^2-2ag\equiv0(\mod x^n) g2+a22ag0(modxn)
两边同乘 f f f
g + a 2 f − 2 a ≡ 0 ( m o d    x n ) g+a^2f-2a\equiv0(\mod x^n) g+a2f2a0(modxn)
g = 2 a − a 2 f ( m o d    x n ) g=2a-a^2f(\mod x^n) g=2aa2f(modxn)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
#define ll long long
const int mod=998244353;
int a[N<<2],b[N<<2],rev[N<<2],limit,lim;
int f[N<<2],g[N<<2];
int n;
int poww(int a,int b,int c){
    int ans=1,base=a;
    while(b){
        if(b&1)ans=1ll*ans*base%c;
        base=1ll*base*base%c;
        b>>=1;
    }
    return ans;
}
void fft(int *a,int type){
    for(int i=0;i<limit;i++)if(rev[i]>i)swap(a[i],a[rev[i]]);
    for(int mid=1;mid<limit;mid<<=1){
        int wn=poww(3,type==1?(mod-1)/(mid<<1):(mod-1-(mod-1)/(mid<<1)),mod);
        for(int i=0;i<limit;i+=(mid<<1)){
            int w=1;
            for(int j=0;j<mid;j++,w=1ll*w*wn%mod){
                int x=a[i+j],y=1ll*w*a[i+j+mid]%mod;
                a[i+j]=(x+y)%mod,a[i+j+mid]=(x+mod-y)%mod;
            }
        }
    }
    if(type==-1){
        int inv=poww(limit,mod-2,mod);
        for(int i=0;i<limit;i++)a[i]=1ll*a[i]*inv%mod;
    }
}
void solve(int n,int *f,int *g){
    if(n==1){
        g[0]=poww(f[0],mod-2,mod);
        return;
    }
    solve((n+1)/2,f,g);
    limit=1,lim=0;
    while(limit<(n<<1))limit<<=1,lim++;
    for(int i=0;i<limit;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lim-1)),a[i]=b[i]=0;
    for(int i=0;i<n;i++)a[i]=f[i],b[i]=g[i];
    fft(a,1),fft(b,1);
    for(int i=0;i<limit;i++)a[i]=1ll*b[i]*((2ll-1ll*b[i]*a[i]%mod+mod)%mod)%mod;
    fft(a,-1);
    for(int i=0;i<n;i++)g[i]=a[i];//注意这里是n不是limit
}
int main(){
   // freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)cin>>f[i];
    solve(n,f,g);
    for(int i=0;i<n;i++)cout<<g[i]<<" ";cout<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值