洛谷P4238 【模板】多项式乘法逆

https://www.luogu.com.cn/problem/P4238

#include<cstdio>
#include<algorithm>

using namespace std;

#define N 300001

const int mod=998244353;
const int g=3;

int n;
long long a[N],b[N],c[N];
int rev[N];

long long poww(long long p,long long q)
{
    long long an=1;
    for(;q;q>>=1,p=p*p%mod)
        if(q&1) an=an*p%mod;
    return an; 
}

void ntt(long long *h,int m,int f)
{
    for(int i=0;i<m;++i)
        if(i<rev[i]) swap(h[i],h[rev[i]]);
    for(int i=1;i<m;i<<=1)
    {
        long long wn=poww(g,(mod-1)/(i*2));
        if(f<0) wn=poww(wn,mod-2);
        for(int j=0,p=i<<1;j<m;j+=p)
        {
            long long w=1;
            for(int k=0;k<i;++k,w=w*wn%mod)
            {
                long long x=h[j+k],y=w*h[j+k+i]%mod;
                h[j+k]=(x+y)%mod; h[j+k+i]=(x-y+mod)%mod;
            }
        }
    }
    if(f<0)
    {
        long long inv=poww(m,mod-2);
        for(int i=0;i<m;++i) h[i]=h[i]*inv%mod;
    }
}


void work(int m,long long *b)
{
    if(m==1)
    {
        b[0]=poww(a[0],mod-2);
        return;
    }
    work(m+1>>1,b);
    int len=1,nn,mm=2*m-1;
    for(nn=0;len<mm;len<<=1,++nn);
    for(int i=1;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<nn-1);
    for(int i=0;i<m;++i) c[i]=a[i];
    for(int i=m;i<len;++i) c[i]=0;
    ntt(c,len,1);
    ntt(b,len,1);
    for(int i=0;i<len;++i) b[i]=((2-b[i]*c[i])%mod+mod)%mod*b[i]%mod;
    ntt(b,len,-1);
    for(int i=m;i<len;++i) b[i]=0;
}

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