列表

详情


WY60. 骰子游戏

描述

小易参加了一个骰子游戏,这个游戏需要同时投掷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

原站题解

C 解法, 执行用时: 2ms, 内存消耗: 232KB, 提交时间: 2019-04-05

#include<stdio.h>
#include<string.h>
#define N_MAX 25
#define X_MAX 125
long long dp[N_MAX+1][X_MAX+1];
long long gcd(long long a, long long b){
    while(b!=0){
        long long tmp = a%b;
        a = b;
        b = tmp;
    }
    return a;
}
int main(int argc,char*argv[]){
    int n, x;
    scanf("%d %d",&n,&x);
    if(x<=n){
        printf("1");
        return 0;
    }
    if(x>6*n){
        printf("0");
        return 0;
    }
    memset(dp,0,sizeof(dp));
    for(int i = 1; i <= n; i++){
        //i个骰子,数字和最小值i,最大值6*i
        for(int j = i; j <= 6*i; j++){
            //当骰子数为1,或骰子数等于可以获得奖励的最小数字和,或最小数字和为极限最大值(6*i)
            //可能的骰子组合为1
            if(i == 1 || i == j || j == 6*i) 
                dp[i][j] = 1;
            else{
                //i-1个骰子的情况
                for(int k = 1; k <= 6; k++){
                    if(j-k>=i-1){
                        dp[i][j]+=dp[i-1][j-k];
                    }
                }
            }
        }
    }
    long long sum = 0;
    long long win_count = 0;
    for(int s = n; s <= 6 * n; s++){
        sum += dp[n][s];
        if(s >= x){
            win_count +=dp[n][s]; 
        }
    }
    long long g = gcd(sum,win_count);
    sum = sum/g;
    win_count = win_count/g; 
    printf("%lld/%lld",win_count, sum);
    return 0;
    
}
    

C 解法, 执行用时: 2ms, 内存消耗: 368KB, 提交时间: 2020-10-29

#include <stdio.h>
#include <string.h>
#define maxn 30
#define maxx 150
typedef long long ll;
int n,x;  //n-骰子数 x-可获得奖励的最小数字和
ll dp[maxn][maxx];  //i个筛子产生数字和j的可能情况数
ll Gcd(ll a,ll b){
    if(b==0)
        return a;
    else
        return Gcd(b,a%b);
}
int main(){
    int i,j,k;
    ll sum,p,gcd;
    scanf("%d %d",&n,&x);
    if(x==n)  //最小数字和=骰子数, 则一定能获得奖励
        printf("1\n");
    else if(x>6*n)  //最小数字和<所有骰子上面均为6时的数字之和, 则一定不能获得奖励
        printf("0\n");
    else{
        memset(dp,0,sizeof(dp));  //初始化
        for(i=1;i<=n;i++){
            for(j=i;j<=6*i;j++){
                if(i==1 || i==j || j==6*i)
                    dp[i][j]=1;
                else{
                    for(k=1;k<=6;k++){
                        if(j-k>=i-1)
                            dp[i][j]+=dp[i-1][j-k];
                    }
                }
            }
        }
        sum=p=0;
        for(i=n;i<=6*n;i++){
            if(i>=x)
                p+=dp[n][i];
            sum+=dp[n][i];
        }
        gcd=Gcd(p,sum);
        printf("%lld/%lld\n",p/gcd,sum/gcd);
    }
    return 0;
}

上一题