CF1626F A Random Code Problem
给出一个序列 \(\{a_i\}\),执行以下内容:
long long ans = 0; // create a 64-bit signed variable which is initially equal to 0 for(int i = 1; i <= k; i++) { int idx = rnd.next(0, n - 1); // generate a random integer between 0 and n - 1, both inclusive // each integer from 0 to n - 1 has the same probability of being chosen ans += a[idx]; a[idx] -= (a[idx] % i); }
求 \(ans\) 的期望值,\(n \le 10^7, k \le 17, a_i \le 10^9\)。
期望
我们发现 \(k \le 17\),因此,设 \(M = \mathrm{lcm}(1, 2, \dots, 17) = 12252240\),可以发现,每个数 \(x\) 有 \(x \bmod~M\) 的部分是会改变的,其他部分是不会变的,于是每个数可以将不变的部分计入答案,然后 \(\bmod~M\) ,于是问题的值域缩小到了 \(M\),可以直接维护 \(f_{i, j}\) 表示通过 \(i - 1\) 次操作后,值为 \(j\) 的期望个数。
于是答案为
\[\sum \frac{f_{i, j} \times j}{n}
\]
考虑转移,每个数有 \(\frac{1}{n}\) 的概率被操作,否则不变,于是根据期望的线性性:
\[\left\{
\begin{aligned}
f_{i, j} \times \frac{1}{n} &\to f_{i + 1, j}\\
f_{i, j} \times \frac{n - 1}{n} &\to f_{i + 1, j - (j~\bmod~i)}
\end{aligned}
\right.
\]
然后 \(f\) 可以滚动数组优化,复杂度 \(\mathcal O(Mk)\)。但是要注意常数问题,特别是我 C++14 直接 T 了,C++17 就可以了。
本博客作者:Werner_Yin(https://www.cnblogs.com/werner-yin/) ,转载时请注明出处,谢谢支持!