1. 程式人生 > >n個硬幣反面朝上,拋m次,一次可以拋k枚硬幣,正面朝上得概率

n個硬幣反面朝上,拋m次,一次可以拋k枚硬幣,正面朝上得概率

    題意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;
}