目录

P4721-【模板】分治 FFT

P4721-【模板】分治 FFT

题目:

题目描述:

给定序列 $g_{1\dots n - 1}$,求序列 $f_{0\dots n - 1}$。

其中 $f_i=\sum_{j=1}^if_{i-j}g_j$,边界为 $f_0=1$。

答案对 $998244353$ 取模。

输入格式:

第一行一个整数 $n$ 。

第二行 $n-1$ 个整数 $g_{1\dots n - 1}$。

输出格式:

一行 $n$ 个整数,表示 $f_{0\dots n - 1}$ 对 $998244353$ 取模后的值。

样例:

样例输入 1:

1
2
4
3 1 2

样例输出 1:

1
1 3 10 35

样例输入 2:

1
2
10
2 456 32 13524543 998244352 0 1231 634544 51

样例输出 2:

1
1 2 460 1864 13738095 55389979 617768468 234028967 673827961 708520894

思路:

实现:

 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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#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 = 1; i < n; i++)
        yin >> a[i], a[i] = mod - a[i];
    a[0] = 1;
    // 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;
}