2 条题解
-
2
可恶的蠕虫,我连题都看不到。
思路
我们根据期望的定义,有
$$\text{期望}=\sum\text{概率}\cdot\text{价值}=\sum\frac{1}{\text{总方案数}}\cdot\text{价值}=\frac{1}{\text{总方案数}}\cdot\sum\text{价值}=\frac{\text{总价值}}{\text{总方案数}}$$总方案数是简单的(题目甚至都告诉你了),为 ,难点在于求总价值。
考虑固定最大值 ,对于每个变量 ,它对答案的贡献是 。
答案就是
这个怎么求呢?
先考虑简单情况:
$$x_1\text{ }x_2\text{ }x_3\\y_1\text{ }y_2\\z_1\text{ }z_2$$在 中选一个、 中选一个、 中选一个,相乘再求和,这个东西我们会这样算:
$$ans=\\x_1y_1z_1+x_1y_1z_2+x_1y_2z_1+x_1y_2z_2+\\ x_2y_1z_1+x_2y_1z_2+x_2y_2z_1+x_2y_2z_2+\\ x_3y_1z_1+x_3y_1z_2+x_3y_2z_1+x_3y_2z_2$$然后再乘法分配律一下,
$$ans=x_1y_1z_1+x_1y_1z_2+\cdots+x_3y_2z_2\\=(x_1+x_2+x_3)(y_1+y_2)(z_1+z_2)$$我们记 表示 的答案,根据刚才的公式,
$$f(h)=\prod_{i=1}^n\sum_{x_i=l_i}^{\min(r_i,h)}(h-x_i+1)$$是可以通过等差数列求和 求的,所以我们可以在 求出 ,那我们再容斥一下就可以求出最大值恰好为 时的答案,为 ,即去掉 的答案
代码
复杂度:外层枚举 ,里面 求出 和 ,总时间复杂度为 。
-
st和ed分别表示 的最小值和最大值,显然 (因为 至少这么多), (因为 至多这么多); -
now表示 的价值总和pre表示 的价值总和; -
calc表示 的值。
// sequence #include <iostream> using namespace std; const int MOD = 1e9 + 7; int n, l[1005], r[1005], sum, cnt = 1, st, ed; int quick_pow(int x, int y) { int res = 1; while (y) { if (y & 1) res = 1ll * res * x % MOD; x = 1ll * x * x % MOD; y >>= 1; } return res; } int calc(int l, int r, int h) { // sum of (h - x + 1), x in [l, r] int sum_x = 1ll * (l + r) * (r - l + 1) / 2ll % MOD; return (1ll * (r - l + 1) * (h + 1) % MOD - sum_x + MOD) % MOD; } int main() { freopen("sequence.in", "r", stdin); freopen("sequence.out", "w", stdout); scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d%d", &l[i], &r[i]); cnt = 1ll * cnt * (r[i] - l[i] + 1) % MOD; st = max(st, l[i]); ed = max(ed, r[i]); } for (int h = st; h <= ed; ++h) { int now = 1, pre = 1; for (int i = 1; i <= n; ++i) { now = 1ll * now * calc(l[i], min(r[i], h), h) % MOD; pre = 1ll * pre * calc(l[i], min(r[i], h - 1), h) % MOD; } sum = (sum + (now - pre + MOD) % MOD) % MOD; } int ans = 1ll * sum * quick_pow(cnt, MOD - 2) % MOD; printf("%d\n", ans); return 0; } -
信息
- ID
- 2817
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 12
- 已通过
- 8
- 上传者