Loading

题解-P5162 WD与积木[*easy]

由于要算的是概率,所以要算的东西分成两个部分 :所有情况的答案总和 和 情况数量。

考虑一层积木的 EGF\(G(x) = e^x - 1\)

那么 \(k\) 层积木的 EGF 就是 \((e^x - 1)^k\)

我们要算的第二个东西的 EGF 就是 \(\sum\limits_{i = 1}^{n} G(x)^k = \frac{G(x)^{n + 1} - G(x)}{G(x) - 1} \equiv \frac{G(x)}{G(x) - 1}\)。多项式求逆即可。

我们要算的第一个东西的是 EGF\(\sum\limits_{i = 1}^n i G(x)^i\)

\[\sum\limits_{i = 1}^n \sum\limits_{j=1}^{i} G(x)^i \]

\[\sum\limits_{j=1}^{n} \sum\limits_{i = j}^n G(x)^i \]

\[\sum\limits_{j=1}^{n} \frac{G(x)^{n + 1} - G(x)^j}{G(x) - 1} \]

考虑到 \(G(x)^{n + 1} \equiv 0\),所以是

\[- \frac{1}{G(x) - 1} \sum\limits_{j=1}^{n} G(x)^j \]

\[- \frac{1}{G(x) - 1} \frac{G(x)^{n + 1} - G(x)}{G(x) - 1} \]

\[- \frac{1}{G(x) - 1} \frac{G(x)^{n + 1} - G(x)}{G(x) - 1} \]

\[\frac{G(x)}{(G(x) - 1)^2} \]

代码:

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++) 
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define ull unsigned long long 
#define db double
#define pii pair<int, int>
#define mkp make_pair
using namespace std;
const int mod = 998244353, G = 3, iG = (mod + 1) / G, N = 3e5, MAXN = 1e5;
int qpow(int x, int y = mod - 2) {
	int res = 1;
	for(; y; x = (ll) x * x % mod, y >>= 1) if(y & 1) res = (ll) res * x % mod;
	return res;
}
int lim, pp[N];
void poinit() { L(i, 0, lim - 1) pp[i] = ((pp[i >> 1] >> 1) | ((i & 1) * (lim >> 1))); }
void up(int len) { lim = 1; for(; lim <= len; lim <<= 1); }
void NTT(int *f, int flag) {
	L(i, 0, lim - 1) if(pp[i] < i) swap(f[pp[i]], f[i]);
	for(int i = 2; i <= lim; i <<= 1) 
		for(int j = 0, l = (i >> 1), ch = qpow(flag == 1 ? G : iG, (mod - 1) / i); j < lim; j += i) {
			for(int k = j, now = 1; k < j + l; k ++) {
				int pa = f[k], pb = (ll) f[k + l] * now % mod;
				f[k] = (pa + pb) % mod, f[k + l] = (pa - pb + mod) % mod, now = (ll) now * ch % mod;
			}
		}
	if(flag == -1) {
		int ilim = qpow(lim);
		L(i, 0, lim - 1) f[i] = (ll) f[i] * ilim % mod;
	}
}
int sav[N];
void cle(int *f) { fill(f, f + lim, 0); }
void inv(int *f, int *g, int len) {
	if(len == 1) return g[0] = qpow(f[0]), void();
	inv(f, g, (len + 1) >> 1), up(len << 1), poinit(), cle(sav), copy(f, f + len, sav), NTT(sav, 1), NTT(g, 1);
	L(i, 0, lim - 1) g[i] = (ll) g[i] * (2 + mod - (ll) sav[i] * g[i] % mod) % mod;
	NTT(g, -1), fill(g + len, g + lim, 0);
}
int fac[N], ifac[N];
void minit(int x) {
	fac[0] = 1;
	L(i, 1, x)  fac[i] = (ll) fac[i - 1] * i % mod;
	ifac[x] = qpow(fac[x]);
	R(i, x, 1) ifac[i - 1] = (ll) ifac[i] * i % mod;
}
int g[N], f[N], ans[N];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	minit(MAXN);
	L(i, 0, MAXN) g[i] = ifac[i]; 
	g[0] = mod - 1, inv(g, ans, MAXN + 1), g[0] = 0, up(MAXN * 2), poinit(), NTT(ans, 1), NTT(g, 1);
	L(i, 0, lim - 1) f[i] = mod - (ll) g[i] * ans[i] % mod, ans[i] = (ll) ans[i] * ans[i] % mod;
	NTT(f, -1), NTT(ans, -1), fill(ans + MAXN + 1, ans + lim, 0), NTT(ans, 1);
	L(i, 0, lim - 1) ans[i] = (ll) ans[i] * g[i] % mod;
	NTT(ans, -1);
	int T, n; cin >> T;
	while(T--) cin >> n, cout << (ll) ans[n] * qpow(f[n]) % mod << endl;
	return 0;
} 
posted @ 2021-01-16 12:40  zhoukangyang  阅读(96)  评论(0编辑  收藏  举报