1. 程式人生 > >2017烏魯木齊區域賽A(動態規劃,組合數學,期望)

2017烏魯木齊區域賽A(動態規劃,組合數學,期望)

ble set 可能 組合 name main i++ return soft

#include<bits/stdc++.h>
using namespace std;
double c[110][110];
double g[110];
double dp[110][110];
int n,m,k;
void cnm()
{
c[0][0]=1;
for(int i=1;i<=100;i++)
{
c[i][0]=1;
c[i][i]=1;
for(int j=1;j<i;j++)
{
c[i][j]=c[i-1][j-1]+c[i-1][j];//組合數挑選硬幣可能的數量
}

}
}
void gailv()//預處理i枚向上的概率
{
g[0]=1;
for(int i=1;i<=100;i++)
g[i]=g[i-1]/2;
}
int main()
{
cnm();
gailv();
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
memset(dp,0,sizeof(dp));
scanf("%d%d%d",&n,&m,&k);
dp[0][0]=1;
for(int j=0;j<m;j++)

{
for(int l=0;l<=n;l++)
{
for(int p=0;p<=k;p++)//拋k枚硬幣有p枚向上
{
if(k+l<=n)//原本向上的枚數加上這次向上的枚數不超過n
{
dp[j+1][l+p]+=dp[j][l]*c[k][p]*g[k];
}
else//超過n的話就會有已經向上的被重拋,導致向上的概率變低

{
dp[j+1][n+p-k]+=dp[j][l]*c[k][p]*g[k];
}
}
}
}
double sum=0;
for(int i=1;i<=n;i++)
{
sum+=dp[m][i]*i;//概率乘上權值
}
printf("%.3f\n",sum);//切勿使用%.3lf
}
return 0;
}

2017烏魯木齊區域賽A(動態規劃,組合數學,期望)