由于期望的线性性,我们可以知道:我们所求的期望实际上就是$\sum\limits_i p'_i \times d_i$,其中$p'_i$为$r$轮中打出过第$i$张卡的概率。
如果没有“一张卡造成伤害后直接结束这一轮”的限制,我们可以很轻松的得到$p'_i = 1 - (1-p_i)^r$,但是如果有这一个限制,实际上也不是很难算……
我们考虑第$i$张卡造成伤害的概率,其实只跟前$i-1$张卡打出了多少张有关,假如前$i-1$张卡中打出了$j$张,那么第$i$张卡就只会在$r-j$轮中被考虑到,那么$p'_i=\sum\limits_{j=0}^{min\{r-1,i-1\}}\text{前i-1张卡中打出j张卡的概率} \times (1-(1-p_i)^{r-j})$。我们考虑计算前$i-1$张卡中打出$j$张卡的概率,可以使用$DP$。设$f_{i,j}$表示前$i$张卡中打出了$j$张卡的概率,初值$f_{0,0}=1$,转移分两种:①第$i$张卡没有被打出;②第$i$张卡被打出,分别计算求和即可。最后计算上面的概率式子,然后题目就做完了qaq
1 #include<bits/stdc++.h> 2 #define ld long double 3 //This code is written by Itst 4 using namespace std; 5 6 inline int read(){ 7 int a = 0; 8 bool f = 0; 9 char c = getchar(); 10 while(c != EOF && !isdigit(c)){ 11 if(c == '-') 12 f = 1; 13 c = getchar(); 14 } 15 while(c != EOF && isdigit(c)){ 16 a = (a << 3) + (a << 1) + (c ^ '0'); 17 c = getchar(); 18 } 19 return f ? -a : a; 20 } 21 22 ld dp[250][150] , p[250]; 23 int d[250] , N , R; 24 25 int main(){ 26 #ifndef ONLINE_JUDGE 27 freopen("3239.in" , "r" , stdin); 28 //freopen("3239.out" , "w" , stdout); 29 #endif 30 for(int T = read() ; T ; --T){ 31 N = read(); 32 R = read(); 33 for(int i = 1 ; i <= N ; ++i){ 34 scanf("%Lf" , &p[i]); 35 d[i] = read(); 36 } 37 memset(dp , 0 , sizeof(dp)); 38 dp[0][0] = 1; 39 for(int i = 1 ; i <= N ; ++i){ 40 for(int j = 1 ; j <= R && j <= i ; ++j) 41 dp[i][j] = dp[i - 1][j - 1] * (1 - pow(1 - p[i] , R - j + 1)); 42 for(int j = 0 ; j <= R && j < i ; ++j) 43 dp[i][j] += dp[i - 1][j] * pow(1 - p[i] , R - j); 44 } 45 ld ans = 0; 46 for(int i = 1 ; i <= N ; ++i){ 47 ld sum = 0; 48 for(int j = 0 ; j < R ; ++j) 49 sum += dp[i - 1][j] * (1 - pow(1 - p[i] , R - j)); 50 ans += sum * d[i]; 51 } 52 printf("%.10Lf\n" , ans); 53 } 54 return 0; 55 }