网易试题
小易参加了一个骰子游戏,这个游戏需要同时投掷n个骰子,每个骰子都是一个印有数字1~6的均匀正方体。
小易同时投掷出这n个骰子,如果这n个骰子向上面的数字之和大于等于x,小易就会获得游戏奖励。
小易想让你帮他算算他获得奖励的概率有多大。
输入描述:
输入包括两个正整数n和x(1 ≤ n < 25, 1 ≤ x < 150),分别表示骰子的个数和可以获得奖励的最小数字和。
输出描述:
输出小易可以获得奖励的概率。 如果概率为1,输出1,如果概率为0,输出0,其他以最简分数(x/y)的形式输出。 示例1
输入
3 9
输出
20/27
思路:动态规划
新建两个数组dp[0]和dp[1],设置标志符flag(0/1)dp[flag][i]为上一次的和为i的个数;dp[1-flag][i]为这次和为i的个数。所以dp[1-flag][i]=dp[flag][i-1]+...+dp[1-flag][i-6];然后再更新flag。
#include<bits/stdc++.h>
using namespace std;
//求最大公约数
long gcd(long a,long b){
if(b==0)
return a;
return gcd(b,a%b);
}
int main(){
int n,x;
scanf("%d%d",&n,&x);
int maxn=6*n;
long* dp[2];
dp[0]=new long[maxn+1];
dp[1]=new long[maxn+1];
int flag=0;
long res=0;
long sumres=0;
for(int i=0;i<=maxn;i++){
dp[flag][i]=0;
dp[1-flag][i]=0;
}
for (int i=1;i<=6;i++){
dp[flag][i]=1;
}
/*/
典型的错误,有些位置上的数没有清零!!!
for(int i=2;i<=n;i++){
for(int j=1;j<=maxn;j++){
for(int k=1;k<=6;k++){
if (j>k){
dp[1-flag][j]+=dp[flag][j-k];
}
else
break;
}
}
flag=1-flag;
}
/*/
for(int i=2;i<=n;i++){
for(int j=0;j<i;j++)
dp[1-flag][j]=0;//当算到第n张牌时,前n-1张牌和<n的个数为0;
for(int j=i;j<=maxn;j++){
dp[1-flag][j]=0;//当算到n张牌时,先初始化为0;
for(int k=1;k<=6;k++){
if (j>k){
dp[1-flag][j]+=dp[flag][j-k];
}
else
break;
}
}
flag=1-flag;
}
for(int i=x;i<=maxn;i++){
res=res+dp[flag][i];
}
sumres=(long)pow(6,n);
long count=gcd(res,sumres);
if(res==0){
printf("%d",res);
}
else if(sumres==res){
printf("%d",sumres/res);
}
else
printf("%ld/%ld",res/count,sumres/count);
delete[] dp[0];
delete[] dp[1];
}