AT_abc323_e Playlist 题解
AT_abc323_e Playlist 题解
一道概率论和动态规划的题,这里的题解主要是翻译原文和个人理解。
问题陈述
有一个包含 \(n\) 首歌曲的播放列表。歌曲 \(i\space(1 \leq i \le n)\) 的长度为整数 \(t_i\) 秒。从第 \(0\) 秒开始随机播放该播放列表。
随机播放重复以下步骤:从 \(n\) 首歌曲中以相等的概率选择一首歌曲,将该歌曲播放完。一首歌播放完,另一首歌就会立即开始播放。同一首歌可以连续选择。
求歌曲 \(1\) 在 \((x + 0.5)\) 秒正在播放的概率(即第 \(1\) 首歌正在被播放),答案对 \(998244353\) 取模。
如何取模
可以证明,本题中要求得的概率总是一个有理数。另外,这个问题的约束条件保证了当要求得的概率用既约分数 \(\frac{y}{x}\) 表示时,\(x\) 不能被 \(998244353\) 整除。
那么,在 \(0\) 和 \(998244352\)(含)之间有一个唯一的整数 \(z\),使得 \(xz \equiv y \pmod{998244353}\),请输出 \(z\)。
题目分析
设 \(f(i)\) 为在第 \(i\) 秒切换歌曲的概率,\(i\in[0,x]\),对 \(998244353\) 取模。
事件「歌曲 \(1\) 在 \(x+0.5\) 秒播放」,与事件「该歌曲在 \(x,(x-1),\ldots,(x-t_1+1)\) 秒开始播放」是互斥的,即这些事件只可能有一个发生。
因此,只需求得歌曲 \(1\) 在时间 \(i\in\{x,(x-1),\ldots,(x-t_1+1)\}\) 的概率之和即可。
因为歌曲的长度一定为整数,因此如果歌曲 \(1\) 在其中某一个时间 \(i\) 播放,那么这首歌曲一定在 \(x+0.5\) 秒正在播放。
因为选择歌曲的概率相等,因此歌曲 \(1\) 在时间 \(i\) 开始播放的概率为任意歌曲在时间 \(i\) 开始播放的概率的 \(\frac{1}{n}\)。
因此,\(\text{ans}=\frac{1}{n}\sum_{j=\max\{x-t_1+1,0\}}^{x}f_j\)。
因此,只需找到每个 \(f(i)\) 即可,可以通过动态规划计算。
显然的,\(f(0)=1\),\(f(i)=\frac{1}{n}\sum_{j=1}^{n}f(i-t_j)\)。
可以这么理解,对于 \(i\ge1\),我们考虑哪首歌曲在 \(i\) 时刻结束,这样 \(p(i)\) 就可以表示为:歌曲 \(j\in[1,n]\) 在 \((i-t_j)\) 时刻开始的概率。正如我们已经讨论过的,\(i-t_j<0\Rightarrow0\),\(i-t_j\ge0\Rightarrow\frac{1}{n}\times f(i-t_j)\)。因此计算 \(f(i)=\frac{1}{n}(f[i-t_1]+f[i-t_2]+\cdots+f[i-t_n])\) 就足够了。
计算每个 \(f(i)\) 需要花费 \(\mathcal{O}(n)\) 时间,计算所有 \(i\in[1,x]\) 的总时间复杂度是 \(\mathcal{O}(nx)\);然后,计算答案需要花费 \(\mathcal{O}(\min\{t_1,x\})\)时间。因此,总体复杂度为 \(\mathcal{O}(nx)\),足以快速解决问题。
注意除法取模需要用到模意义下的乘法逆元,详见我的文章:https://www.cnblogs.com/RainPPR/p/linear-congruence-equation-and-inverse.html。
示例代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;
#define rr(x) read<x>()
template<typename _tp>
inline _tp read() {
_tp num = 0, flag = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') flag = -1;
for (; isdigit(ch); ch = getchar()) num = num * 10 + ch - '0';
return num * flag;
}
ll qpow(ll a, ll b, ll mod) {
ll res = 1;
for (; b; b >>= 1, a = a * a % mod) if (b & 1) res = res * a % mod;
return res;
}
int t[1010];
ll f[20010];
int main() {
int n = rr(int), x = rr(int);
int vn = qpow(n, MOD - 2, MOD);
for (int i = 1; i <= n; ++i) t[i] = rr(int);
f[0] = 1; for (int i = 1; i <= x; ++i) {
for (int j = 1; j <= n; ++j) if (i >= t[j]) f[i] = (f[i] + f[i - t[j]]) % MOD;
f[i] = f[i] * vn % MOD;
} ll res = 0; for (int i = max(0, x - t[1] + 1); i <= x; ++i) {
res = (res + f[i]) % MOD;
} res = res * vn % MOD;
printf("%lld\n", res);
return 0;
}
本文来自博客园,作者:RainPPR,转载请注明原文链接:https://www.cnblogs.com/RainPPR/p/solution-AT_abc323_e.html
如有侵权请联系我(或 2125773894@qq.com)删除。