【数学】骰子问题

骰子问题

 

    问题描述:

    众所周知,骰子是一个六面分别刻有1到6点的立方体,每次投掷骰子,从理论上讲得到1点到6点的概率都是1/6。今有骰子一颗,连续投掷n次,问点数总和大于x的概率是多少?

    输入格式:

仅有一行,包含两个用空格隔开的整数,分别表示n和x,其中1<=n<=24,0<=x<150。


   
输出格式:

输出文件仅有一行,为一个分数。要求以最简的形式精确地表达出连续投掷n次骰子,总点数大于等于x的概率。

   
输入:

3 9


   
输出:

20/27

  

    试题分析:

     好,现在我告诉你分数原型是160/216,你是否明白了呢?

     没错,216就是6^3,因为每一次扔骰子可以有1~6任意一种,

     那么和(不考虑重复的)就为6^3

     这是总的种数,那么160是什么呢?

     就是满足大于等于X的方法数(方法数也不考虑重复)

     那么就可以设F(i,j)为要组成等于i,扔j次骰子的方法种数

     可以得到,我们可以循环加上去的1~6(k),再循环现在的数字(j)

     那么可以得到F(i,j)=sum(F(k+j,i+1)) (0≤i<N,0≤j≤i*6,0<l<7)

  

    代码如下(压位不会啊QAQ):

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
LL f[1001][1001];
LL N,X;
LL tmp=1;
LL ans;
long long Gcd(LL a,LL b){//最大公约数
	if(b==0) return a;
	return Gcd(b,a%b);
}
int main(){
	cin>>N>>X;
	f[0][0]=1;
	for(LL i=0;i<N;i++){
		tmp*=6;//(216)
		for(LL j=0;j<=i*6;j++)//枚举现在的数字
		    for(LL k=1;k<=6;k++)
		        f[k+j][i+1]+=f[j][i];
	}
	for(LL i=X;i<=6*N;i++) ans+=f[i][N];//(ans=160),加上符合条件的方法数
	LL K=Gcd(ans,tmp);
	ans/=K,tmp/=K;//约分
	if(tmp==1) cout<<1;
	else cout<<ans<<"/"<<tmp;
}

  

 

 

posted @ 2016-12-19 15:50  wxjor  阅读(1250)  评论(0编辑  收藏  举报