Description
牛客网 2018校招真题 骰子游戏
Solving Ideas
参考《剑指offer》n个骰子的点数
考虑用两个数组来存储骰子点数的每一个总数出现的次数。
- 在一次循环中,第一个数组中的第n个数字表示骰子和为n出现的次数。
- 在下一循环中,我们加上一个新的骰子,此时和为n的骰子出现的次数等于上一次循环中骰子点数和为n-1、n-2、n-3、n-4、n-5与n-6的次数的总和
- 所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1、n-2、n-3、n-4、n-5与n-6个数之和
Solution
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* https://blog.csdn.net/qq_32767041/article/details/86420299
*
* @author wylu
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] strs = br.readLine().split(" ");
int n = Integer.parseInt(strs[0]), x = Integer.parseInt(strs[1]);
//骰子最大面值
int diceMaxVal = 6;
//count[][n]: 点数和为n出现的次数
long[][] count = new long[2][diceMaxVal * n + 1];
int flag = 0;
for (int i = 1; i <= diceMaxVal; i++) count[flag][i] = 1;
for (int k = 2; k <= n; k++) {
//有k个骰子时,最小点数和为k,不存在出现点数和小于k的情况
for (int i = 1; i < k; i++) count[1 - flag][i] = 0;
for (int i = k; i <= diceMaxVal * k; i++) {
count[1 - flag][i] = 0;
for (int j = 1; j < i && j <= diceMaxVal; j++) {
count[1 - flag][i] += count[flag][i - j];
}
}
//在下一轮中,交换两个数组,通过改变flag实现
flag = 1 - flag;
}
long sum = 0, total = (long) Math.pow(diceMaxVal, n);
for (int i = x; i <= diceMaxVal * n; i++) sum += count[flag][i];
long maxDivisor = gcd(total, sum);
if (sum == 0) System.out.println(0);
else if (sum == total) System.out.println(1);
else System.out.println((sum / maxDivisor) + "/" + (total / maxDivisor));
}
private static long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
}