quq
题意:
有 \(n(\leq 10^6)\) 个数的数组 \(a(a_i \leq 10^7)\),对于每一个 \(a_i\),操作一次可以等概率得到 \(1 \sim a_i\) 的任意一个数。
求在最优策略下,得到所有可能获得的数 \((1 \sim \max a_i)\) 的期望次数。
期望
首先,最优策略一定是将按 \(a\) 从大到小抽出数,没抽出就一直抽,因为在 \(a\) 较大可以抽出 \(a\) 较小的数,反过来就不可以。
对于一个要抽出来的数 \(i\), 那么就要找到一个最近的 \(a_i\), 记为 \(b\)。
由于期望的线性性,考虑当前 \(i\) 的对总期望的贡献,要算出能单独抽出 \(i\) 期望次数和概率。
- 单独抽出 \(i\) 的期望就是 \(E(b)\),在 \(b\) 中抽出 \(i\), 就有:
记 \(k = \frac{b - 1}{b}\), 求:
\[\sum_{i = 1}^{\infty} k^{i - 1}\cdot i \]注意到 \((k^{i})' = i \cdot k ^{i - 1}\), 对这个式子进行一个积分。
得到:
\[\sum_{i = 1}^{\infty} k^i \]用生成函数表示:
\[f(x) = \frac{k}{1 - k} \]导回去:
\[f'(x) = \frac{1 \cdot (1 - k) - (- 1) \cdot k}{(1 - k)^2} = \frac{1}{(1 - k)^2} = b^2 \]因为:
\[b\cdot E(b) = f'(x) = b^2 \]所以:
\[E(b) = b \]- 求出概率,\(i + 1 \sim \max a_i\) 都抽完的概率。
令 \(s = \max a_i - i + 1\)。
直接钦定 \(i\) 最后一个选,那么就有:
\[f_i = \frac{(s - 1)!}{s!} = \frac{1}{s} \]求和即可
\[\text{ans} = \sum_{i = 1}^{\max a_i} i \times {f_i} \]代码:
#pragma GCC optimize(2)
#include
using namespace std;
template
void Read(T &x) {
x = 0; T f = 1; char a = getchar();
for(; a < '0' || '9' < a; a = getchar()) if (a == '-') f = -f;
for(; '0' <= a && a<= '9'; a = getchar()) x = (x * 10) + (a^ 48);
x *= f;
}
const int mod = 19260817;
int add(int a, int b) {
int c = a + b;
if (c < 0) c += mod;
if (c >= mod) c -= mod;
return c;
}
int mul(int a, int b) {
return 1ll * a * b % mod;
}
int qpow(int a, int b) {
int sum = 1;
while(b) {
if (b & 1) sum = mul(sum, a);
a = mul(a, a);
b >>= 1;
}
return sum;
}
const int MAXN = 1000010;
int n, m;
int a[MAXN];
int f[MAXN * 10], ifa[MAXN * 10];
int inv[MAXN * 10];
int main() {
freopen("quq.in", "r", stdin);
freopen("quq.out", "w", stdout);
Read(n);
int ma = 0;
for(int i = 1; i <= n; i ++)
Read(a[i]), ma = max(ma, a[i]);
sort(a + 1, a + n + 1);
inv[1] = 1;
for(int i = 2; i <= ma; i ++)
inv[i] = mul(mod - mod / i, inv[mod % i]);
int ans = 0;
for(int i = n; i; i --)
for(int j = a[i]; j > a[i - 1]; j--)
ans = add(ans, mul(a[i], inv[a[n] - j + 1]));
cout << ans;
return 0;
}