n个骰子的点数

思路:
一个骰子有6个面,点数分别是1,2,3,4,5,6,那么n个骰子的最小点数和为n,最大点数和为6n;

1、当只有一枚骰子时,它只有6种结果,即和为1,2,3,4,5,6这6种,抛一次骰子时每种结果都只可能会出现1次;
2、当有n枚骰子时,抛一次时的最小点数和为n,最大点数和为6n,其他的点数和在这之间,当求点数和为k(n<k<6n)的出现次数,那f(k) = f(k-1)+f(k-2)+f(k-3)+f(k-4)+f(k-5)+f(k-6);

那么我们用数组下标(最小点数和为n,下标从n计算开始,比n小的不赋值)代表点数和,数组对应的值代表该点数和出现的次数,数组的大小应该是: 骰子最大点数×骰子数+1;

我们用两个数组,其中一个用来存放上一轮骰子各个点数和对应的次数,另一个用来存放当新加入一个骰子的时候各个点数和对应的次数。
n个骰子的点数
代码如下:

/**
 * @ClassName TestDemo60
 * @Description 面60
 * @Author lzq
 * @Date 2019/1/28 9:45
 * @Version 1.0
 **/
public class TestDemo60 {

      // 骰子最大点数
    int maxValue = 6;

    public TestDemo60(int maxValue) {
        this.maxValue = maxValue;
    }

    /**
     * 计算number骰子各个点数和出现的概率
     * @param number
     */
    public void get_probability(int number) {
        /**
         * 用来保存所有可能出现的点数和的数组其下标从0开始到
         * 最大点数和number*maxValue结束
         */
        int length = number*maxValue+1;

        //probability1用来保存上一次骰子的每个点数和出现次数
        double[] probability1 = new double[length];
        //probability2用来计算当新加入当前骰子的时候,每个点数和出现次数
        double[] probability2 = new double[length];

        /**
         * 初始化第一个骰子的的点数和,只有一枚骰子时,各个点数和都是1
         */
        for(int i = 1;i <= maxValue;i++) {
            probability2[i] = 1;
        }

        int count = 1; //计数器,用来记录滑动窗口里面的数值是否超过maxValue
        double sum = 0; //用来计算当前点数和出现的次数

        Deque<Double> deque = new ArrayDeque<>(); //保存滑动窗口

        /**
         * 计算第二枚到第number枚骰子各个点数和出现的次数
         */
        for(int k = 2;k <= number;k++) {
            //将上一次的骰子各个点数和给probability1,记得用clone,否则只是改变了指针指向
            probability1 = probability2.clone();
            //重置probability2,将其清零,用于保存当前骰子的各个点数和
            for(int i = 0;i <= (k-1)*maxValue;i++) {
                probability2[i] = 0;
            }
            //将双端队列清空,用于保存上一次骰子的各个点数和的滑动窗口
            deque.clear();
            count = 1;
            sum = 0;
            /**
             * 计算当前骰子的各个点数和出现的次数
             */
            for(int j = k;j <= k*maxValue;j++) {
                if(count <= maxValue) {
                    //如果当前计算的点数和小于maxValue,只需要累加即可
                    sum += probability1[j-1];
                }else {
                    //如果当前计算的点数和大于maxValue,需要删除队列第一个元素
                    sum = sum-deque.getFirst()+probability1[j-1];
                    deque.removeFirst();
                }
                probability2[j] = sum;
                deque.offerLast(probability1[j-1]);
                count++;
            }
        }

        double all = Math.pow(maxValue,number); //所以可能出现的次数总和
        System.out.println("点数和"+"\t出现次数"+"\t概率");
        for(int i = number;i < length;i++) {
            System.out.print(i+"\t");
            System.out.print(probability2[i]+"\t\t");
            System.out.print(probability2[i]/all+"\n");  //概率
        }

   }
 }

测试代码:

public static void main(String[] args) {
        TestDemo60 testDemo60 = new TestDemo60(6);
        testDemo60.get_probability(3);
    }

运行结果:

点数和	出现次数	概率
3	1.0		0.004629629629629629
4	3.0		0.013888888888888888
5	6.0		0.027777777777777776
6	10.0		0.046296296296296294
7	15.0		0.06944444444444445
8	21.0		0.09722222222222222
9	25.0		0.11574074074074074
10	27.0		0.125
11	27.0		0.125
12	25.0		0.11574074074074074
13	21.0		0.09722222222222222
14	15.0		0.06944444444444445
15	10.0		0.046296296296296294
16	6.0		0.027777777777777776
17	3.0		0.013888888888888888
18	1.0		0.004629629629629629