题意:给定序列长度n,通过元音字母a,e,i,o,u以及以下的规则进行组合,问满足条件的组合数;
- 每个元音 ‘a’ 后面都只能跟着 ‘e’
- 每个元音 ‘e’ 后面只能跟着 ‘a’ 或者是 ‘i’
- 每个元音 ‘i’ 后面 不能 再跟着另一个 ‘i’
- 每个元音 ‘o’ 后面只能跟着 ‘i’ 或者是 ‘u’
- 每个元音 ‘u’ 后面只能跟着 ‘a’
由于答案可能会很大,所以请你返回模10e9+7之后的结果。
传送门
题解一:DP,dp[i][j]表示以j结尾的长度为i的组合数,0-4表示a-u
int countVowelPermutation(int n) {
#define ll long long
int mod = 1e9 + 7;
vector<ll> dp(5, 1), tmp(5);
for (int i = 2; i <= n; ++i) {
tmp[0] = (dp[1]+dp[2]+dp[4]) % mod;
tmp[1] = (dp[0]+dp[2]) % mod;
tmp[2] = (dp[1]+dp[3]) % mod;
tmp[3] = dp[2];
tmp[4] = (dp[2]+dp[3]) % mod;
dp = tmp;
}
ll ret = 0;
for (auto &x : dp) ret = (ret+x) % mod;
return ret;
}
题解二:矩阵快速幂
#define ll long long
#define Matrix vector<vector<ll>>
const int mod = 1e9+7;
class Solution {
public:
Matrix multiply(Matrix &matrixA, Matrix &matrixB) {
int m = matrixA.size(), n = matrixB[0].size();
Matrix res(m, vector<ll>(n));
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
for (int k = 0; k < matrixA[i].size(); ++k)
res[i][j] = (res[i][j] + matrixA[i][k] * matrixB[k][j]) % mod;
return res;
}
Matrix fastPow(Matrix &matrix, ll n) {
int m = matrix.size();
Matrix res(m, vector<ll>(m, 0)), curr(matrix);
for (int i = 0; i < m; ++i)
res[i][i] = 1;
for (int i = n; i != 0; i >>= 1) {
if (i & 1) res = multiply(curr, res);
curr = multiply(curr, curr);
}
return res;
}
int countVowelPermutation(int n) {
Matrix factor = {{0, 1, 0, 0, 0},
{1, 0, 1, 0, 0},
{1, 1, 0, 1, 1},
{0, 0, 1, 0, 1},
{1, 0, 0, 0, 0}};
Matrix res = fastPow(factor, n-1);
ll ret = 0;
for (auto &v : res)
for (auto &x : v)
ret = (ret+x) % mod;
return ret;
}
};