骰子
描述
骰子是一个六面分别刻有一到六点的立方体,每次投掷骰子,理论上得到1到6的概率都是1/6
有骰子一颗,连续投掷n次,问点数总和大于等于X的概率是多少
输入
输入一行2个证书,分别表示n,X,其中1<=N<=24,0<=X<150
输出
1行,一个分数,要求用最简的形式精确的表达投掷n次骰子,总数大于等于x的概率。如果是0/1,则输出0,如果1/1输出1
样例输入
3 9
样例输出
20/27
分析
入门入门入门入门
好好分析一下
其实不用想那么多,简单理解,概率=合法情况的次数/总次数
那么对于这道题其合法情况就是投 n 次后总点数>=x
总方案数就是 6^n
难点就在合法情况的个数上
我们可以想到dp(不要问为什么【皮】)
定义状态 f[i][j]表示 投了 i 次,总点数为 j 的方案数
显然转移就是 f[i][j]=sum{f[i-1][j-k]}(1<=k<=6)
最后合法的情况就是 f[n][x~6*n]
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll f[30][200];
ll gcd(ll x,ll y){
ll z=x%y;
while(z){x=y;y=z;z=x%y;}
return y;
}
int main(){
int n,x;
scanf("%d%d",&n,&x);
int i,j,k;
for(i=1;i<=6;++i) f[1][i]=1;
for(i=2;i<=n;++i){
for(j=1;j<=6*i;++j)
for(k=1;k<=6;++k)
if(j>k) f[i][j]+=f[i-1][j-k];
}
ll tot=1;
for(i=1;i<=n;++i) tot*=6;
ll ans=0;
for(i=x;i<=6*n;++i)
ans+=f[n][i];
if(!ans) return printf("0"),0;
if(tot==ans) return printf("1"),0;
ll gd=gcd(ans,tot);
cout<<ans/gd<<'/'<<tot/gd;
return 0;
}