Submit: 1952 Solved: 1159
[Submit][Status][Discuss]
Description
小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑。
Input
输入文件的第一行包含一个整数 T,代表测试数据组数。
Output
对于每组数据,输出一行,包含一个实数,为这套卡牌在这一局游戏中造成的
Sample Input
3 2
0.5000 2
0.3000 3
0.9000 1
Sample Output
HINT
一共有 13 种可能的情况:
Source
感觉期望的题都好绕啊qwq。。
首先根据期望的线性,每个位置对BOSS造成的伤害都是独立的。
根据期望的定义而且此题中每个位置只允许攻击一次,我们只需算出每个位置在$r$轮中出现的概率即可
这个概率为$1 - (1 - p[i])^r$,即总的概率减去一次都没出现的概率
但是这题有一个特殊限制“如果前面的打出了,那么本轮游戏结束”,也就是说如果$i - 1$位置打出了,那么$i$位置本次肯定是不能出现的
这样的话,如果$i$前面一共有$j$个位置打出了,也就是$i$有$j$次强制没被打出,那么$i$出现的概率为$1 - (1 - p[i])^{r - j}$
考虑这玩意儿如何计算,设$f[i][j]$表示前$i$个中强制打出了$j$个的概率
这显然是可以递推完成的,讨论一下这个位置是否打出就行了
那么$g[i] = \sum_i f[i][j] * (1 - (1 - p[i])^{r - j})$
最终答案为$ans = \sum g[i] * d[i]$
// luogu-judger-enable-o2 // luogu-judger-enable-o2 #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #define LL long long using namespace std; const int MAXN = 200000, INF = 1e9 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, R; double f[1001][1001],/*前i轮中,恰好有j张牌发动了攻击的概率*/ P[1001], D[1001], PowP[1001][1001], G[1001]; void GetPow() { for(int i = 1; i <= N; i++) { PowP[i][0] = 1; for(int j = 1; j <= R; j++) PowP[i][j] = PowP[i][j - 1] * (1 - P[i]); } } main() { int QWQ; scanf("%d", &QWQ); while(QWQ--) { memset(f, 0, sizeof(f)); scanf("%d %d", &N, &R); for(int i = 1; i <= N; i++) scanf("%lf %lf", &P[i], &D[i]); GetPow(); f[1][1] = G[1] = 1 - PowP[1][R]; f[1][0] = PowP[1][R]; for(int i = 2; i <= N; i++) { G[i] = 0; for(int j = 0; j <= min(i, R); j++) { if(j) f[i][j] += f[i - 1][j - 1] * (1 - PowP[i][R - j + 1]); //发动攻击,那么R-j+1轮中不会出现 if(i != j) f[i][j] += f[i - 1][j] * PowP[i][R - j]; //第i张牌始终没有出现过 G[i] += f[i - 1][j] * (1 - PowP[i][R - j]); } } double ans = 0; for(int i = 1; i <= N; i++) ans += G[i] * D[i]; printf("%.10lf\n", ans); } return 0; }