uva 10759 throw dice

原题:
n common cubic dice are thrown. What is the probability that the sum of all thrown dice is at least x?
Input
The input file contains several test cases. Each test case consists two integers n (1 ≤ n ≤ 24) and x
(0 ≤ x < 150). The meanings of n and x are given in the problem statement. Input is terminated by a
case where n =0 and x =0. This case should not be processed.
Output
For each line of input produce one line of output giving the requested probability as a proper fraction
in lowest terms in the format shown in the sample output. All numbers appearing in output are
representable in unsigned 64-bit integers. The last line of input contains two zeros and it should not
be processed.
Sample Input
3 9
1 7
24 24
15 76
24 56
24 143
23 81
7 38
0 0
Sample Output
20/27
0
1
11703055/78364164096
789532654692658645/789730223053602816
25/4738381338321616896
1/2
55/46656

大意:
给你n个骰子,一次扔出,问你这n个骰子的总和大于大于等于x的概率是多少?

#include<iostream>
#include<algorithm>
#include<map>
#include<string>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<iomanip>
#include<set>
#include<fstream>
#include <limits.h>
using namespace std;
//fstream output,input;

long long dp[25][151];
long long six[25];
long long tmp,ans;
long long gcd(long long a,long long b)
{
    return b==0 ? a: gcd(b,a%b);
}
int main()
{
    ios::sync_with_stdio(false);
    int n,x;
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1;i<=24;i++)
    {
        for(int j=0;j<=150;j++)
        {
            tmp=0;
            for(int k=1;k<=6&&k<=j;k++)
            {
                tmp+=dp[i-1][j-k];
            }
            dp[i][j]=tmp;
        }
    }
    six[0]=1;
    for(int i=1;i<=24;i++)//6的n次幂
        six[i]=six[i-1]*6;
    while(cin>>n>>x,x+n)
    {
        if(x<=n)
        {
            cout<<1<<endl;
            continue;
        }
        ans=0;
        for(int i=x;i<=150;i++)
        {
            ans+=dp[n][i];
        }
        long long q =six[n];
        tmp=gcd(ans,q);
        if(ans==0)
            cout<<0<<endl;
        else
            cout<<ans/tmp<<'/'<<q/tmp<<endl;
    }
// input.close();
// output.close();
    return 0;
}




解答:
多个状态的概率求解问题一般都是动态规划。首先设置状态,很好考虑,因为一共就两个状态,一个状态是骰子数,另一个状态是要投出的数记为dp[i][j]表示用i个骰子扔出j的概率。接下来状态转移,
dp[ i ][ j ] = sigma(dp[i-1][j-k])*(1/6) 其中1<=k<=6,表示前i-1个骰子骰子扔出j-k个点数的概率乘以第i个骰子扔出的点数k的概率。
不过此题不是让人简单的求解概率,而是要算成分数的形式。考虑到分母一定是6的n次幂,所以计算转移方程的时候只算分子就行,所以帮上面的方程的那个1/6去掉即可,用long long 求最大公约数,分子分母分别约去即可。注意6的n次幂不要用pow计算,会丢位数。

你可能感兴趣的:(dp,uva)