#514. 【UR #19】通用测评号
#514. 【UR #19】通用测评号
一个小 $\tt trick$:
考虑填充的结束条件,就是恰好有一个燃料舱是 $b$ 单位的。
而且因为期望是线性的,我们直接对于每个燃料舱进行计算概率即可。最终的答案就是 $(n - 1) \times P$。
我们将 $z = 1$ 带入即可。
那么我们考虑一下这个 $P$ 是怎么计算的,我们不妨考虑拿出最后一个是 $b$ 的燃料舱,那么就是 $n$。为了方便我们设 $f(x)$ 表示进行了 $x$ 次操作的概率函数,也就是 $\dfrac{z^x}{x!n^x}$。
显然最后一个仓就是 $f(B - 1) \times \frac{1}{n} \times n = f(B - 1)$。
之后对于其他仓我们只要保证至少一个是符合条件即可,那么就是 $(e^x - f(A - 1)) \times (e^x - f(B - 1)) ^{n - 2}$。
所以得到:$P = f(B - 1)\times(e^z - f(A - 1)) \times (e^z - f(B - 1)) ^{n - 2}$
发现 $e^z$ 实际上是无限项的,我们考虑将 $e^{\frac{az}{n}} \times \dfrac{z^b}{b!}\times C$ 进行展开。
别忘了我们最后算的是 $ogf$ 所以之后还要还要将其转化成 $ogf$。
我们展开一手(不用管 $C$,毕竟是常数):
$$
\begin{aligned}
&\sum_{i \ge 0} \frac{z^{b + i}a^i}{i!b!n^i} \
=&z^b \sum_{i \ge 0} \binom{i + b}{i}\frac{a^iz^i}{n^i}\
=&\frac{z^b}{(1 - \frac{i}{n}z)^{b + 1}}
\end{aligned}
$$
这里补充一下:
$$
\frac{1}{(1 - z)^b} = \sum_{i \ge 0} \binom{i - (-b) - 1}{i} z^i
$$
这个就是上指标翻转(后面其实有 $(-1)^{2i}$)。
我们对于卷积的部分直接进行 $dft$ 后点乘即可。
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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| #include <bits/stdc++.h> using namespace std;
namespace Legendgod {
namespace Read {
#ifdef Fread const int Siz = (1 << 21) + 5; char buf[Siz], *iS, *iT; #define gc() (iS == iT ? (iT = (iS = buf) + fread(buf, 1, Siz, stdin), iT == iS ? EOF : *iS ++ ) : *iS ++) #define getchar gc #endif
template <typename T> void r1(T &x) { x = 0; int f(1); char c(getchar()); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) x = (x * 10) + (c ^ 48); x *= f; } template <typename T, typename...Args> void r1(T &x, Args&...arg) { r1(x), r1(arg...); }
}
using namespace Read;
const int maxn = 2e5 + 5; const int maxm = 250 + 5; constexpr int mod = 998244353; constexpr int G = 3, invG = 332748118;
int rev[maxn];
int ksm(int x,int mi) { int res(1); while(mi) { if(mi & 1) res = 1ll * res * x % mod; mi >>= 1; x = 1ll * x * x % mod; } return res; }
int lim, len; int w[2][maxn];
void FFT(int *A,int opt = 1) { for(int i = 0; i < lim; ++ i) if(i < rev[i]) swap(A[i], A[rev[i]]); for(int mid = 1; mid < lim; mid <<= 1) { for(int j = 0, c = (mid << 1); j < lim; j += c) { for(int k = 0; k < mid; ++ k) { int x = A[j + k], y = 1ll * w[(opt != 1)][mid + k] * A[j + k + mid] % mod; A[j + k] = (x + y) % mod; A[j + k + mid] = (x - y + mod) % mod; } } } if(opt != 1) { int z = ksm(lim, mod - 2); for(int i = 0; i < lim; ++ i) A[i] = 1ll * A[i] * z % mod; } }
int fac[maxn], inv[maxn], invf[maxn];
void init(int x) { fac[0] = inv[0] = 1; for(int i = 1; i <= x; ++ i) fac[i] = 1ll * fac[i - 1] * i % mod; invf[x] = ksm(fac[x], mod - 2); for(int i = x - 1; i >= 0; -- i) invf[i] = 1ll * invf[i + 1] * (i + 1) % mod; for(int i = 1; i <= x; ++ i) inv[i] = 1ll * fac[i - 1] * invf[i] % mod; }
int n, A, B; int pw[maxn];
int C(int a,int b) { return a < b ? 0 : 1ll * fac[a] * invf[b] % mod * invf[a - b] % mod; }
int f1[maxn], f2[maxn];
int f[maxm][maxm * maxm];
signed main() { int i, j; init(maxn - 5); r1(n, A, B); int up = (n - 1) * B + A - 1; lim = 1, len = 0; while(lim <= up) lim <<= 1, ++ len; for(i = 0; i < lim; ++ i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1)); for(int mid = 1; mid < lim; mid <<= 1) { int wn = ksm(G, (mod - 1) / (mid << 1)), w1 = 1; for(int j = 0; j < mid; ++ j) w[0][mid + j] = w1, w1 = 1ll * w1 * wn % mod; } for(int mid = 1; mid < lim; mid <<= 1) { int wn = ksm(invG, (mod - 1) / (mid << 1)), w1 = 1; for(int j = 0; j < mid; ++ j) w[1][mid + j] = w1, w1 = 1ll * w1 * wn % mod; } pw[0] = 1; for(i = 1; i <= up; ++ i) pw[i] = 1ll * pw[i - 1] * inv[n] % mod; for(i = 0; i < B; ++ i) f1[i] = (mod - 1ll * pw[i] * invf[i] % mod) % mod; for(i = 0; i < A; ++ i) f2[i] = (mod - 1ll * pw[i] * invf[i] % mod) % mod; FFT(f1, 1), FFT(f2, 1); for(i = 0; i < lim; ++ i) f[0][i] = 1; for(i = 1; i <= n - 2; ++ i) { for(j = 0; j < lim; ++ j) f[i][j] = 1ll * f[i - 1][j] * f1[j]% mod; } for(i = 0; i <= n - 2; ++ i) { int tmp = C(n - 2, i); for(j = 0; j < lim; ++ j) f[i][j] = 1ll * f[i][j] * tmp % mod; } for(i = n - 2; i >= 0; -- i) { for(j = 0; j < lim; ++ j) f[i + 1][j] = (f[i + 1][j] + 1ll * f[i][j] * f2[j] % mod) % mod; } for(i = 0; i <= n - 1; ++ i) FFT(f[i], - 1); int ans(0); for(i = 0; i <= n - 1; ++ i) { int tmp1 = 1ll * invf[B - 1] * pw[B - 1] % mod, tmp2 = 1ll * n * inv[i + 1] % mod; for(j = 0; j < B - 1; ++ j) tmp1 = 1ll * tmp1 * tmp2 % mod; for(j = 0; j <= up; ++ j) { tmp1 = 1ll * tmp1 * tmp2 % mod; ans = (ans + 1ll * f[i][j] * tmp1 % mod * fac[j + B - 1] % mod) % mod; } } ans = 1ll * ans * (n - 1) % mod; printf("%d\n", ans); return 0; }
}
signed main() { return Legendgod::main(), 0; }
|