题目参考:不同骰子序列的数目
题解:动态规划
1、状态定义f[i][j][k]:前i个数,以k、j结尾的满足条件的序列个数
2、状态转移:f[i][j][k] = Sum(f[i-1][k][w]);满足条件 j != k && k != w && j != w,gcd(j, k) == gcd(k, w) == 1;时间复杂度为O(n*6^3)
代码示例:
class Solution {
public:
using ll = long long;
ll mod = 1e9 + 7;
int distinctSequences(int n) {
if(n == 1) return 6;
// 暴力预处理出[1, 6]内每两个数的最大公因数
vector<vector<int>> gcd(6, vector<int>(6));
for(int i = 1; i <= 6; i++){
for(int j = 1; j <= 6; j++){
for(int k = min(i, j); k >= 1; --k)
if(i % k == 0 && j % k == 0) {
gcd[i - 1][j - 1] = k;
break;
}
}
}
vector<vector<vector<ll>>> f(n, vector<vector<ll>>(6, vector<ll>(6, 0)));
for(int i = 0; i < 6; i++){
for(int j = 0; j < 6; j++){
if(gcd[i][j] == 1 && i != j) f[1][i][j] = 1;
}
}
for(int i = 2; i < n; i++){
for(int j = 0; j < 6; j++){
for(int k = 0; k < 6; k++){
if(gcd[j][k] != 1 || j == k) continue;
for(int w = 0; w < 6; w++){
if(w != j && gcd[k][w] == 1){
(f[i][j][k] += f[i - 1][k][w]) %= mod;
}
}
}
}
}
ll res = 0;
for(int i = 0; i < 6; i++){
for(int j = 0; j < 6; j++){
if(gcd[i][j] == 1 && i != j) (res += f[n - 1][i][j]) %= mod;
}
}
return res;
}
};