题目:
将N个相同的硬币排成一排,所有的硬币正面朝上向下放到桌子上,尾巴向上,然后执行K次操作每次取一枚硬币,抛出得到正面或反面。最后正面朝上的硬币可以拿走。问可以赢得的最大预期金额是多少?
思路:
期望公式 (Ex = A * p(A)) A表示是一个事件,P(A)是A发生的概率。这道题也是这样想的。最后正面朝上的个数num
可能是1~n个。所以(res = num * P(num))。问题变为求P(num),即最后num个硬币正面朝上的概率。
用dp求P(num)。我们用dp[i][j]表示i次操作后有j个正面朝上的概率,这样总共k次操作,所以P(num)=dp[k][num]。 如何转移呢?我们已知dp[0][0] = 1;
当正面朝上个数j小于n时,我们要优先对正面朝下的硬币先操作,每次操作后抛出硬币有可能正有可能背面向上。所以由dp[i][j]可以更新dp[i+1][j]和dp[i+1][j+1]。
j < n 时,dp[i + 1][j + 1] += dp[i][j] * 0.5;
dp[i + 1][j] += dp[i][j] * 0.5;
当正面朝上个数j等于n时,我们只能选正面向上的硬币操作,有正有负,所以可能会减少向上个数。所以do[i][n]可以更新dp[i+1][j]和dp[i+1][j-1];
j == n 时 dp[i+1][j] += dp[i][j] * 0.5;
dp[i+1][j-1] += dp[i][j] * 0.5;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e3 + 105;
const int mod = 998244353;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
//
int n, k;
double dp[N][N];
int main()
{
scanf("%d%d",&n,&k);
memset(dp, 0,sizeof(dp));
dp[0][0] = 1;
for(int i = 0; i < k; ++ i){
for(int j = 0; j < n; ++ j){
dp[i + 1][j] += dp[i][j] * 0.5;
dp[i + 1][j + 1] += dp[i][j] * 0.5;
}
dp[i + 1][n] += dp[i][n] * 0.5;
dp[i + 1][n - 1] += dp[i][n] * 0.5;
}
double res = 0;
for(int i = 1; i <= n; ++ i){
res += i * dp[k][i];
}
printf("%.6lf
",res);
return 0;
}