题目链接:uva 10759 - Dice Throwing
题目大意:给出n和x,计算在丢n个色子,出现的点数大于等于x的概率,要求分式最简。
解题思路:一开始方向想错了,一直在枚举num[i][j], i表示i个色子丢出的点数小于x的情况,一直找不到状态转移方程,推出来几个都是错的,算了一下午;后来发现num[i][j] 与num[i][j + 1]中间的增长个数与用i个色子丢出的点数为j的情况有关,然而求用i个色子丢出点数的情况则是非常好求的:num[i][j] = ∑(j + 1 ≤ k ≤ j + 6)num[i][k].
然后就可以进一步的去求丢出i个色子丢出的点数小于x的情况。
#include <stdio.h>
#include <string.h>
int n, x;
long long num[30][160], sum[30];
void init() {
memset(num, 0, sizeof(num));
for (int i = 1; i <= 6; i++) num[1][i] = 1;
sum[0] = 1;
for (int i = 1; i <= 24; i++) {
sum[i] = sum[i - 1] * 6;
for (int j = 1; j <= 150; j++) {
for (int k = 1; k <= 6; k++)
num[i + 1][j + k] += num[i][j];
num[i][j] += num[i][j - 1];
}
}
}
long long gcd(long long a, long long b) {
return b == 0 ? a : gcd (b, a % b);
}
int main () {
init();
long long a, b, d;
while (scanf("%d%d", &n, &x), n || x) {
x--;
if (sum[n] == num[n][x]) printf("0\n");
else {
d = gcd(sum[n] - num[n][x], sum[n]);
a = (sum[n] - num[n][x]) / d;
b = sum[n] / d;
if (b == 1) printf("1\n");
else
printf("%lld/%lld\n", a, b);
}
}
return 0;
}