洛谷传送门
题目背景
也可用多项式求逆解决。
题目描述
给定长度为 的数组 ,求 ,其中
边界为 。答案模 。
输入输出格式
输入格式:
第一行一个正整数 。
第二行共 个非负整数 ,用空格隔开。
输出格式:
一行共 个非负整数,表示 模 的值。
输入输出样例
输入样例#1:
4
3 1 2
输出样例#1:
1 3 10 35
输入样例#2:
10
2 456 32 13524543 998244352 0 1231 634544 51
输出样例#2:
1 2 460 1864 13738095 55389979 617768468 234028967 673827961 708520894
说明
解题分析
这道题后面的值由一部分前面的贡献得到, 可以使用cdq分治的思想分治计算。 具体而言, 对于一个区间 , 我们先递归计算 的答案, 再计算 对 的贡献, 即对应 与 的卷积, 最后计算 的答案。
复杂度 。
然而FFT被卡精度了, 只好用NTT代替…
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define ll long long
#define G 3ll
#define Ginv 332748118ll
#define MOD 998244353ll
#define R register
#define W while
#define IN inline
#define gc getchar()
#define MX 400050
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
W (!isdigit(c)) c = gc;
W (isdigit(c))
x = (x << 1) + (x << 3) + c - 48, c = gc;
}
IN ll fpow(ll now, ll tim)
{
ll ret = 1;
for (R unsigned i = 0; i <= 31; ++i, now = now * now % MOD)
if(tim & (1 << i)) ret = ret * now % MOD;
return ret;
}
ll a[MX], b[MX], mul[MX], ans[MX];
int len, rev[MX];
IN void NTT(ll *dat, const int &tot, R bool typ)
{
for (R int i = 0; i < tot; ++i) if(rev[i] < i) std::swap(dat[i], dat[rev[i]]);
R int now, cur, bd, step, seg;
ll tar1, tar2, base, deal;
for (seg = 1; seg < tot; seg <<= 1)
{
base = fpow(typ ? G : Ginv, (MOD - 1) / (seg << 1)); step = seg << 1;
for (now = 0; now < tot; now += step)
{
deal = 1, bd = now + seg;
for (cur = now; cur < bd; ++cur, deal = deal * base % MOD)
{
tar1 = dat[cur], tar2 = dat[cur + seg] * deal % MOD;
dat[cur] = (tar1 + tar2) % MOD; dat[cur + seg] = ((tar1 - tar2) % MOD + MOD) % MOD;
}
}
}
if(typ) return;
ll inv = fpow(tot, MOD - 2);
for (R int i = 0; i < tot; ++i) dat[i] = dat[i] * inv % MOD;
}
void cdq(R int lef, R int rig)
{
if(lef == rig) return;
R int bd, tot = 1, lg = 0, siz = rig - lef + 1, mid = lef + rig >> 1;
cdq(lef, mid);
bd = siz << 1;
W (tot <= bd) tot <<= 1, ++lg;
for (R int i = 0; i < tot; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)),
a[i] = b[i] = 0;
for (R int i = lef; i <= mid; ++i) a[i - lef] = ans[i];
for (R int i = 0; i < siz; ++i) b[i] = mul[i];
NTT(a, tot, 1), NTT(b, tot, 1);
for (R int i = 0; i < tot; ++i) a[i] = a[i] * b[i] % MOD;
NTT(a, tot, 0);
for (R int i = mid + 1; i <= rig; ++i)
ans[i] = (ans[i] + a[i - lef - 1] % MOD + MOD) % MOD;
cdq(mid + 1, rig);
}
int main(void)
{
in(len); --len; ans[0] = 1;
for (R int i = 0; i < len; ++i) in(mul[i]);
cdq(0, len);
for (R int i = 0; i <= len; ++i) printf("%lld ", ans[i]);
}