:::info[Description] Link. :::
:::infoSolution 在上一题中已经得到了可以 计算的答案形式 ,现在考虑将其优化到严格线性时间复杂度解决。
现在令 ,做一个随机试验:有 个人,每个人独立的以概率 被选中,设最终选中了 个人,对一次确定的结果, 表示在选中的人中有顺序允许重复的选择 次的方案书。
现在换一个角度数这 次选择。假设这 个位置中实际出现了 个不同的人,则把 个位置分成 个非空组有 种方案,然后给 个组安排 个不同的人有 种方案,这 个人全部比选中的概率为 。因此有 。然后考虑对“恰好使用 个不同的人”这一限制条件直接做容斥,得到 ,代入原式可得 ,交换求和可得 ,其中 。
考虑线性递推 。初始条件显然是 ,递推可以倒推,根据 Pascal 公式可得 。
剩下部分的 也同样可以线性递推,拆一下组合数就可以得到 ,初始条件是 。
最后的答案就是 , 是积性函数直接线性筛求出即可。总时间复杂度被优化到 ,可以通过该题。
需要卡空间。 :::
:::success[Code]
namespace lowspeed_song {
int inv[N], h[N];
inline void init() {
inv[0] = inv[1] = h[0] = 1;
for (int i = 2; i < N; ++i) inv[i] = mod - inv[mod % i] * (mod / i) % mod;
}
unsigned char isp[N];
signed pr[N / 10], idx;
int pwr[N];
inline void sol() {
int n, m, k; cin >> n >> m >> k;
int o = 1, x = inversion(m);
for (int i = 1; i <= min(n, k); ++i) {
o = o * (mod - x) % mod * ((n - min(n, k) + i - 1) % mod) % mod * inv[i] % mod;
h[i] = ((1 - x + mod) % mod * h[i - 1] + o) % mod;
}
pwr[1] = isp[1] = 1;
for (int i = 2; i < N; ++i) {
if (!isp[i]) pr[++idx] = i, pwr[i] = power(i, k, mod);
for (int j = 1; j <= idx && i * pr[j] < N; ++j) {
if (i % pr[j] == 0) break;
isp[i * pr[j]] = 1, pwr[i * pr[j]] = pwr[i] * pwr[pr[j]] % mod;
}
}
int res = 0, w = 1;
for (int i = 0; i <= min(n, k); ++i) {
res = (res + pwr[i] * w % mod * h[min(n, k) - i]) % mod;
if (i < min(n, k)) w = w * ((n - i) % mod) % mod * x % mod * inv[i + 1] % mod;
}
cout << res << '\n';
}
} // namespace lowspeed_song:::
难度:黑-
鲜活指数:6
喜欢的话,留下你的评论吧~