题意
略。
题解
果然是一道板题。我连板题都不会
以下实际上是ural那题的题解。
考虑如果直接用拉格朗日插值,复杂度是(mathcal O(n ^ 2))的。
但是这道题要求求点值的(x)很平凡(都是离散的且连着的整数),所以考虑将答案形式化。
考虑我们知道的是(f_0, f_1, ldots, f_n)(平移一下),要求的是(f_{n + 1}, f_{n + 2}, ldots, f_{n + m})。
则
[egin{aligned}
f(n + i)
& = sum_{j = 0} ^ n f(j) frac{prod_{k != j} (n + i - k)}{prod_{k != j} (j - k)} \
& = sum_{j = 0} ^ n f(j) frac{(n + i)(n + i - 1) ldots (n - i - (j - 1)(n - i - (j + 1)) ldots (n + i - n)}{j(j - 1) ldots (j - (j - 1))(j - (j + 1)) ldots (j - n)} \
& = frac{(n + i)!}{(n + i - n - 1)!} sum_{j = 0} ^ n f(j) frac{{(-1)} ^ {n - j}}{j! (n - j)!} frac{1}{n + i - j} \
end{aligned}
]
设(g(i) = f(i) frac{{(-1)} ^ {n - i}}{i! (n - i)!}, h(i) = frac{1}{i}),则
[f(n + i) = frac{(n + i)!}{(i - 1)!} sum_{j = 0} ^ n g(j) h(n + i - j) \
]
然后一个卷积就没了。复杂度(mathcal O((n + m) log (n + m)))。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector <int> poly;
const int N = 1 << 21, mod = 998244353, G = 3;
const ll infty = 1ll * mod * mod;
int power (int x, int y) {
int ret = 1;
y < 0 ? y += mod - 1 : 0;
for ( ; y; y >>= 1, x = 1ll * x * x % mod) {
if (y & 1) {
ret = 1ll * ret * x % mod;
}
}
return ret;
}
namespace {
int adjust (int n) {
int ret = 1;
for ( ; ret < n; ret <<= 1);
return ret;
}
poly trans (int n, int *a) {
int m = adjust(n);
poly ret; ret.resize(m, 0);
for (int i = 0; i < n; ++i) {
ret[i] = a[i];
}
return ret;
}
void dnt (int n, poly &_a, int sgn) {
static int rev[N], a[N], wi[N];
for (int i = 0; i < n; ++i) {
rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? n >> 1 : 0);
a[i] = _a[rev[i]];
}
for (int l = 2, _w; l <= n; l <<= 1) {
_w = power(G, (mod - 1) / l * sgn), wi[l >> 1] = 1;
for (int i = (l >> 1) + 1; i < l; ++i) {
wi[i] = 1ll * wi[i - 1] * _w % mod;
}
}
for (int l = 2, m = 1; l <= n; m = l, l <<= 1) {
for (int i = 0; i < n; i += l) {
int *u = a + i, *v = a + i + m, *w = wi + m;
for (int j = 0, x, y; j < m; ++u, ++v, ++w, ++j) {
x = *u, y = 1ll * (*v) * (*w) % mod;
*u = (x + y) % mod, *v = (x - y + mod) % mod;
}
}
}
int coe = power(n, sgn > 0 ? 0 : -1);
for (int i = 0; i < n; ++i) {
_a[i] = 1ll * a[i] * coe % mod;
}
}
poly conv (int n, poly a, poly b) {
n <<= 1, a.resize(n, 0), b.resize(n, 0);
dnt(n, a, 1), dnt(n, b, 1);
for (int i = 0; i < n; ++i) {
a[i] = 1ll * a[i] * b[i] % mod;
}
dnt(n, a, -1);
return a;
}
}
poly A, B, C;
int n, m, ans;
int a[N], b[N], fac[N], ivf[N], _fac[N], _ivf[N];
void prework () {
fac[0] = 1;
for (int i = 1; i <= n + m + 1; ++i) {
fac[i] = 1ll * fac[i - 1] * i % mod;
}
ivf[n + m + 1] = power(fac[n + m + 1], mod - 2);
for (int i = n + m; ~i; --i) {
ivf[i] = 1ll * ivf[i + 1] * (i + 1) % mod;
}
}
int main () {
scanf("%d%d", &n, &m), --n, prework();
for (int i = 0; i <= n; ++i) {
scanf("%d", &a[i]);
a[i] = 1ll * a[i] * ivf[i] % mod * ivf[n - i] % mod;
a[i] = ((n - i) & 1 ? mod - a[i] : a[i]);
}
for (int i = 0; i <= n + m; ++i) {
b[i] = power(i, mod - 2);
}
A = trans(n + m + 1, a), B = trans(n + m + 1, b);
C = conv(A.size(), A, B);
for (int i = n + 1; i <= n + m; ++i) {
ans = 1ll * fac[i] * ivf[i - n - 1] % mod * C[i] % mod;
printf("%d ", ans);
}
return 0;
}