Leetcode 2318. 不同骰子序列的数目 java

题目链接

2318. 不同骰子序列的数目 - 力扣(Leetcode)

给你一个整数 n 。你需要掷一个 6 面的骰子 n 次。请你在满足以下要求的前提下,求出 不同 骰子序列的数目:

  1. 序列中任意 相邻 数字的 最大公约数 为 1 。
  2. 序列中 相等 的值之间,至少有 2 个其他值的数字。正式地,如果第 i 次掷骰子的值 等于 第 j 次的值,那么 abs(i - j) > 2 。

请你返回不同序列的 总数目 。由于答案可能很大,请你将答案对 109 + 7 取余 后返回。

如果两个序列中至少有一个元素不同,那么它们被视为不同的序列。

示例 1:

输入:n = 4
输出:184
解释:一些可行的序列为 (1, 2, 3, 4) ,(6, 1, 2, 3) ,(1, 2, 3, 1) 等等。
一些不可行的序列为 (1, 2, 1, 3) ,(1, 2, 3, 6) 。
(1, 2, 1, 3) 是不可行的,因为第一个和第三个骰子值相等且 abs(1 - 3) = 2 (下标从 1 开始表示)。
(1, 2, 3, 6) i是不可行的,因为 3 和 6 的最大公约数是 3 。
总共有 184 个不同的可行序列,所以我们返回 184 。

 示例 2:

输入:n = 2
输出:22
解释:一些可行的序列为 (1, 2) ,(2, 1) ,(3, 2) 。
一些不可行的序列为 (3, 6) ,(2, 4) ,因为最大公约数不为 1 。
总共有 22 个不同的可行序列,所以我们返回 22 。

提示: 

  • 1 <= n <= 104

 解题思路

所有递归,传n、前一个数和前前一个数,传递当前枚举的点数的前两个数是为了判断是否满足当前数不与前两个数相同以及当前数和前一个数最大公约数为一;递归出口是当n==0时代表骰子已全部掷完,返回数字1。另外定义一个三维数组用来保存每一次的结果,后续的可以利用前面已保存的值避免重复计算。

Java代码

class Solution {
    static int mod = (int)1e9 + 7;
    static int[][][] tmp = new int[10001][8][8];
    //计算最大公约数
    int gcd(int a, int b){
        return b % a == 0 ? a : gcd(b % a , a);
    }

    public int distinctSequences(int n) {
        return dfs(n, 7, 7);
    }

    int dfs(int n, int last1, int last2){
        //先去保存的结果中查询,如果以及计算直接返回
        if (tmp[n][last1][last2] != 0 ){
            return tmp[n][last1][last2];
        }
        long count = 0;
        //递归出口
        if(n == 0){
            return 1;
        }
        //枚举骰子的点数
        for(int i = 1; i <= 6; i++){
            if(i != last1 && i != last2 && gcd(i, last1) == 1){
                count += dfs(n - 1, i, last1);
            }
        }
        int res = (int)(count % mod);
        //保存结果
        tmp[n][last1][last2] = res;
        return res % mod;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值