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 就可以了

  代码

posted @ 2022-01-19 20:59  Werner_Yin  阅读(78)  评论(5编辑  收藏  举报