P10286 题解
Register_int · · 题解
upd on 2024.7.31:做法太唐,重写。
根据 简单版 的柿子,我们要计算下面这个东西:
先
直接 bostan-mori 计算,时间复杂度
AC 代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
using namespace polynomial; // By R_i.
typedef vector<poly<int>> polyv;
inline
polyv operator * (const polyv &f, const polyv &g) {
int n = f.size(), m = g.size(), x = f[0].size(), y = g[0].size();
poly<int> a(n * (x + y - 1)), b(m * (x + y - 1));
for (int i = 0; i < n; i++) {
for (int j = 0; j < x; j++) a[i * (x + y - 1) + j] = f[i][j];
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < y; j++) b[i * (x + y - 1) + j] = g[i][j];
}
a *= b; polyv res(n + m - 1, poly<int>(x + y - 1));
for (int i = 0; i < n + m - 1; i++) {
for (int j = 0; j < x + y - 1; j++) res[i][j] = a[i * (x + y - 1) + j];
}
return res;
}
poly<int> bostan_mori(int n, polyv f, polyv g) {
if (!n) return f[0] * inv(g[0]);
if (n + 1 < f.size()) f.resize(n + 1);
if (n + 1 < g.size()) g.resize(n + 1);
polyv h = g;
for (int i = 1; i < h.size(); i += 2) h[i] = -h[i];
f = f * h, g = g * h; polyv a, b;
for(int i = n & 1; i < f.size(); i += 2) a.push_back(f[i]);
for(int i = 0; i < g.size(); i += 2) b.push_back(g[i]);
return bostan_mori(n >> 1, a, b);
}
const int MAXN = 1e5 + 10;
int fac[MAXN], ifac[MAXN], tk[MAXN], p2[MAXN];
inline
void init(int n) {
*fac = 1;
for (int i = 1; i <= n; i++) fac[i] = (ll)fac[i - 1] * i % mod;
ifac[n] = qpow(fac[n], mod - 2);
for (int i = n; i; i--) ifac[i - 1] = (ll)ifac[i] * i % mod;
tk[1] = 1;
for (int i = 2; i <= n; i++) tk[i] = qpow(i, i - 2);
*p2 = 1;
for (int i = 1; i <= n; i++) p2[i] = (p2[i - 1] << 1) % mod;
}
int n, k, ans, t = 1, a[MAXN];
poly<int> f, g; polyv p, q;
int main() {
scanf("%d%d", &n, &k), ++n, init(n), f.resize(n), g.resize(n);
for (int i = 0; i < n; i++) g[i] = (ll)t * ifac[i] % mod, t = (ll)t * p2[i + 2 - k] % mod;
for (int i = 0; i < n; i++) f[i] = (ll)tk[i] * ifac[i] % mod;
g *= inv(exp(f)), g.resize(n), f[0]++;
g = g * pow(f, n - 1), f = inv(f) >> 1;
for (int i = 0; i < n; i++) {
p.push_back(vector<int>({ g[i], 0 }));
q.push_back(vector<int>({ !i, mod - f[i] }));
}
g = bostan_mori(n - 1, p, q), g.resize(n), g.reverse();
for (int i = 0; i < n; i++) g[i] = (ll)g[i] * fac[i] % mod;
for (int i = 0; i < n; i++) scanf("%d", &a[i]), ans = (ans + (ll)a[i] * g[i] % mod) % mod;
printf("%lld", ans);
}