题目描述:##
骰子是一个六面分别刻有一到六点的立方体,每次投掷骰子,理论上得到(1)到(6)的概率都是(1/6)。
有骰子一颗,连续投掷(n)次,问点数总和大于等于(X)的概率是多少?
题目分析:##
概率(DP)入门,由于是第一次做这类题,记录一下。
首先概率题的主要思路:
(概率 = 合法方案数 / 总方案数)
对于这道题,总方案数(total=6^n),所以重点在于怎么求合法方案数,即抛掷(n)次总和大于(X)的次数。
考虑(dp),设(f[i][j])表示抽第(i)次总点数为(j)的方案数,容易得到状态转移方程(f[i][j]=sumlimits_{k=1}^6{f[i-1][j-k]})
$ ans = frac{sumlimits_{i=x}^{6*n}{f[n][i]}}{total} $
代码:##
#include<bits/stdc++.h>
#define N 30
#define M 300
using namespace std;
int read() {
int cnt = 0; int f = 1;
char c;
c = getchar();
while (!isdigit(c)) {
if (c == '-') f = -1;
c = getchar();
}
while (isdigit(c)) {
cnt = cnt * 10 + c - '0';
c = getchar();
}
return cnt * f;
}
long long gcd(long long x, long long y) {
if (x == 0) return y;
return gcd(y % x, x);
}
long long f[N][M], n, x, tot = 1, ans = 0;
int main() {
n = read(); x = read();
for (register int i = 1; i <= n; i++) tot *= 6;
f[0][0] = 1;
for (register int i = 1; i <= n; i++)
for (register int j = 1; j <= i * 6; j++)
for (register int k = 1; k <= 6; k++)
if(j - k >= 0)
f[i][j] += f[i-1][j-k];
for (register int i = x; i <= 6 * n; i++)
ans += f[n][i];
if (ans == 0) {
printf("0");
return 0;
}
if (ans == tot) {
printf("1");
return 0;
}
long long GCD = gcd(ans, tot);
ans /= GCD; tot /= GCD;
printf("%lld/%lld", ans, tot);
return 0;
}