目录

P4238-【模板】多项式乘法逆

P4238-【模板】多项式乘法逆

题目:

题目描述:

给定一个多项式 $F(x)$ ,请求出一个多项式 $G(x)$, 满足 $F(x) * G(x) \equiv 1 ( \mathrm{mod:} x^n )$。系数对 $998244353$ 取模。

输入格式:

首先输入一个整数 $n$, 表示输入多项式的项数。
接着输入 $n$ 个整数,第 $i$ 个整数 $a_i$ 代表 $F(x)$ 次数为 $i-1$ 的项的系数。

输出格式:

输出 $n$ 个数字,第 $i$ 个整数 $b_i$ 代表 $G(x)$ 次数为 $i-1$ 的项的系数。 保证有解。

样例:

样例输入 1:

1
2
5
1 6 3 4 9

样例输出 1:

1
1 998244347 33 998244169 1020

思路:

实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "ybwhead/ios.h"
int n, lim, l;
const int maxn=1e6+10;
long long a[maxn], b[maxn];
int r[maxn];
const int mod=998244353;
long long c[maxn];
long long ksm(long long a, int n)
{
    long long ans=1;
    while (n)
    {
        if (n&1)ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
const int g=3, gi=332748118;
void ntt(long long a[], long long x)
{
    for (int i=0;i<lim;i++)if (i<r[i])swap(a[i], a[r[i]]);
    for (int o=2, k=1;o<=lim;o<<=1, k<<=1)
    {
        long long wn=ksm(x, (mod-1)/(o));
        for (int i=0;i<lim;i+=o)
        {
            long long w=1;
            for (int j=0;j<k;j++, w=w*wn%mod)
            {
                long long x=a[i+j], y=a[i+j+k]*w%mod;
                a[j+i]=(x+y)%mod;
                a[j+k+i]=(x-y+mod)%mod;
            }
        }
    }
}
void calc(int n, long long b[])
{
    if (n==1)
    {
        b[0]=ksm(a[0], mod-2);
        // yout<<a[0]
        return;
    }
    calc((n+1)>>1, b);
    lim=1;l=0;
    while (lim<(n<<1))lim<<=1, ++l;
    // yout<<lim<<" "<<a[1]<<endl;
    for (int i=0;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    for (int i=0;i<n;i++)c[i]=a[i];
    for (int i=n;i<lim;i++)c[i]=0;
    ntt(c, g);ntt(b, g);
    for (int i=0;i<lim;i++)
    {
        b[i]=(2-c[i]*b[i]%mod+mod)%mod*b[i]%mod;
        // yout<<b[i]<<endl;
    }
    ntt(b, gi);
    long long inv=ksm(lim, mod-2);
    for (int i=0;i<n;i++)b[i]=(b[i]*inv)%mod;
    for (int i=n;i<lim;i++)b[i]=0;
}
int main()
{
    yin>>n;
    for (int i=0;i<n;i++)yin>>a[i];
    // while (lim<n)lim<<=1, l++;
    calc(n, b);
    for (int i=0;i<n;i++)yout<<(b[i]+mod)%mod<<" ";
    yout<<endl;
    return 0;
}