Play the Dice
The first line is an integer n (2<=n<=200), following with n integers a i(0<=a i<200)
The second line is an integer m (0<=m<=n), following with m integers b i(1<=b i<=n), which are the numbers of the special sides to get another more chance.
6 1 2 3 4 5 6 0 4 0 0 0 0 1 3
3.50 0.00
题意:有一个n面的骰子,掷到第i面,可得a[i]分。其中有m个面,可获得再掷一次的机会,求掷一次得分的期望。
思路:
解法1:总期望等于子期望的加权和,加权因子为子期望发生的概率。
设所求期望为Exp,因为无限掷,当前状态与转移状态的期望趋于同一极限Exp,Exp有m种转移方式,转移概率均为 1 / n , 即:
Exp= 1 / n * ( ( Exp +a [ b[ 1 ] ] ) + ( Exp +a [ b[ 2 ] ] ) + ... + ( Exp + a[ b[ m ] ] ) ) + 1 / n * ( a [ p ] + ... + a [ p' ] )。设sum为a [ i ] 的和, 化简得:
(1- m / n) * Exp= 1 / n * sum ---------> Exp= sum / ( n - m) 。
解法2: 我们只考虑第一次获得得分的期望为sum / n,对于运气好的,摇中了又获得m / n * sum / n ,运气好又再来一次, 获得( m / n ) ^2 * sum / n,
无穷无尽地摇下去,一共能获得 sum / n * ( 1+ p + p^2 + ... + p^k + ...) p=m / n ,式子化简Exp = sum / ( n - m) 。
解法3:我们考虑i面,那么i面出现的概率为p( i )= 1 / n + n / m * 1 / n + ( n / m )^2 * 1 / n + ... + ( n / m)^k * 1 / n + ..... ,等比数列求和得:
p( i )= 1 / ( n - m) ,即Exp(i) =a[ i ] * 1 / ( n- m) , 最后求和 Exp =sum / ( n - m) 。
对以上三种解法,当sum=0, Exp=0; 当 sum !=0 ,m=n ,Exp =inf ; 不然 Exp = sum / ( n- m ),详见程序:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int main()
{
//freopen("text.txt","r",stdin);
while(~scanf("%d",&n))
{
int sum=0,x;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
sum+=x;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
scanf("%d",&x);
if(sum==0)
{
printf("0.00\n");
continue;
}
if(n==m)
{
printf("inf\n");
continue;
}
printf("%.2f\n",sum*1.0/(n-m));
}
return 0;
}