题解:AT_abc314_e [ABC314E] Roulettes

DerRichter Lv2

题意

有 台轮盘。第 台轮盘( )上写有 个整数 ,每次支付 日元可以玩一次。每玩一次第 台轮盘,会等概率随机选出 到 之间的一个整数 ,获得 分。

每次轮盘获得的分数相互独立。

Takahashi 想要获得至少 分。Takahashi 会采取使得在获得至少 分之前所支付金额尽可能小的策略。并且,Takahashi 每次玩轮盘时,可以根据之前所有轮盘的结果选择下一次要玩的轮盘。

请计算 Takahashi 在获得至少 分之前所支付金额的期望值。

思路

首先显然不是贪心。我们可以想象成,每次得到 到 内的任意一个整数,花费 代价,可以转换成完全背包。

发现正推似乎不太好做。所以我们倒退。设计状态 表示当前离 还有 点积分时的代价期望最小值,显然有 。

考虑转移,我们可以写出转移式:

但是存在 ,无法直接做。可以通过数学手段证明其绝对收敛(不写证明过程了,但确实可行),所以可以将其视为方程来看。最终转移式如下:

其中 。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/extc++.h>

using namespace std;
using ll = long long;
using ld = long double;

const int MAXN = 1e2 + 10;
const ll INF = 2e18;

struct Roulette {
int c, p, cnt;
vector<int> s;
} a[MAXN];

int n, m;
ld dp[MAXN << 1];

int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i].c >> a[i].p;
a[i].s.assign(a[i].p + 5, 0);
for (int j = 1; j <= a[i].p; j++) {
cin >> a[i].s[j];
a[i].cnt += !a[i].s[j];
}
}
for (int i = m - 1; i >= 0; i--) {
dp[i] = INF;
for (int j = 1; j <= n; j++) {
ld sum = a[j].p * a[j].c;
for (int k = 1; k <= a[j].p; k++) {
if (!a[j].s[k]) continue;
sum += dp[i + a[j].s[k]];
}
dp[i] = min(dp[i], sum / (a[j].p - a[j].cnt));
}
}
cout << fixed << setprecision(50) << dp[0];
return 0;
}
  • 标题: 题解:AT_abc314_e [ABC314E] Roulettes
  • 作者: DerRichter
  • 创建于 : 2026-08-15 00:01:33
  • 更新于 : 2026-08-15 07:15:59
  • 链接: https://derrichter.onrender.com/2026/08/15/题解:AT-abc314-e-ABC314E-Roulettes/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
题解:AT_abc314_e [ABC314E] Roulettes