n个硬币反面朝上,抛m次,一次可以抛k枚硬币,正面朝上得概率

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sxy201658506207/article/details/86226600

    题意n个硬币反面朝上,抛m次,一次可以抛k枚硬币,问在最优得情况下正面朝上得概率

    最优的情况 每次选的k枚硬币尽量都选反面朝上的

    dp[i][j]表示 第i次抛硬币中j个正面朝上的概率,对于抛k枚硬币,c枚朝上的组合有 C(k,c)种

    对于抛硬币正和反的概率都是0.5,所以抛k次概率为0.5^k
    枚举跑K个正面朝上得个数c 则有C(K,C)个选择,

    dp[i+1][x]=dp[i][j]*C(k,c)*0.5^k x为当前状态所有硬币正面朝上的个数)

    当反面朝上得个数>=k则全部抛反面朝上得,即x=j+c

    反之,会有一部分正面朝上得硬币和全部反面朝上得硬币一块跑,那么这时候没有被抛到得正面朝上得硬币的个数为n-k

    那么这时候得枚举状态就是x=n-k+c
暑假做得一道题,忘记哪儿得了。
 

#include <bits/stdc++.h>
#define X 10005
#define inF 0x3f3f3f3f
#define PI 3.141592653589793238462643383
#define IO  ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
typedef unsigned long long Ull; //2^64
const int maxn = (int)1e6 + 10;
const int MOD = (int)1e9 + 7;
const ll inf = 9223372036854775807;
const int N = 47;
ll primer[maxn];
ll a[maxn];
int ans[maxn], num[maxn];
void ex_gcd(ll a, ll b, ll &d, ll &x, ll &y) { if (!b) { x = 1; y = 0; d = a; } else { ex_gcd(b, a%b, d, y, x); y -= x * (a / b); }; }
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll lcm(ll a, ll b) { return b / gcd(a, b)*a; }
ll inv_exgcd(ll a, ll m) { ll d, x, y;ex_gcd(a, m, d, x, y);return d == 1 ? (x + m) % m : -1; }
ll inv1(ll b) { return b == 1 ? 1 : (MOD - MOD / b)*inv1(MOD%b) % MOD; }
double C[200][200];
double p[200];
double dp[200][200];
int main()
{
	IO;
	int n, m, k;
	C[0][0] = 1;
	p[0] = 1.0;
	for (int i = 1;i <= 150;++i)
	{
		p[i] = p[i - 1] * 0.5;
		for (int j = 0;j <= i;++j)
		{
			C[i][j] =( j==0 ? 1: C[i - 1][j - 1] + C[i - 1][j]);
		}
	}
	int t;cin >> t;
	while (t--) {
		cin >> n >> m >> k;
		//dp[i][j] i次j个在上
		memset(dp,0,sizeof(dp));
		dp[0][0] = 1;
		for (int i = 0;i < m;++i)
		{
			for (int j = 0;j <= n;++j)
			{//cout<<1<<endl;
				for (int c = 0;c <= k;++c)
				{
					if (n - j >= k) dp[i + 1][j + c] += dp[i][j] * C[k][c] * p[k];//+=是在上一个状态转移过来得到
					else dp[i + 1][n - k + c] += dp[i][j] * C[k][c] * p[k];
				}
			}
		}
		double ans = 0.0;
		for (int i = 0;i <= n;++i)
		{
			ans += dp[m][i] * i;
		}
		printf("%.3lf\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sxy201658506207/article/details/86226600