【数学】骰子问题
骰子问题
问题描述:
众所周知,骰子是一个六面分别刻有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; }
你——悟到了么?