题目
思路一 动态规划
根据每个字母后能接的字母来递推,思路很简单。
代码一
class Solution {
public:
int mod=1000000007;
int countVowelPermutation(int n) {
if(n==1) return 5;
if(n==2) return 10;
vector<vector<int>> dp(n+1,vector<int>(5));
dp[2]={1,2,4,2,1};
for(int i=3;i<=n;i++){
dp[i][0]=dp[i-1][1]%mod;
dp[i][1]=(dp[i-1][0]+dp[i-1][2])%mod;
dp[i][2]=((dp[i-1][0]+dp[i-1][1])%mod+(dp[i-1][3]+dp[i-1][4])%mod)%mod;
dp[i][3]=(dp[i-1][2]+dp[i-1][4])%mod;
dp[i][4]=dp[i-1][0]%mod;
}
int sum=0;
for(int i=0;i<5;i++)
sum=(sum+dp[n][i])%mod;
return sum;
}
};优化版
因为我们只需要最后一次dp的结果,前面的结果不需要保存,只需要保存上一次dp的结果,可以节省内存占用空间。
class Solution {
public:
int mod=1000000007;
int countVowelPermutation(int n) {
vector<int> dp(5,1),ndp(5);
while(--n){
ndp[0]=dp[1];
ndp[1]=(dp[0]+dp[2])%mod;
ndp[2]=((dp[0]+dp[1])%mod+(dp[3]+dp[4])%mod)%mod;
ndp[3]=(dp[2]+dp[4])%mod;
ndp[4]=dp[0];
dp=ndp;
}
int sum=0;
for(int x:dp)
sum=(sum+x)%mod;
return sum;
}
};思路二 矩阵快速幂
根据上面的规律,可以把ndp和dp的转换关系写成矩阵的形式。相乘n次又可以转换成快速幂的形式。
代码二
class Solution {
public:
int mod=1e9+7;
vector<vector<long>> mul(vector<vector<long>>& a,vector<vector<long>>& b){
int r=a.size(),c=b[0].size(),z=b.size();
vector<vector<long>> ans(r,vector<long>(c));
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
for(int k=0;k<z;k++){
ans[i][j]+=(a[i][k]*b[k][j])%mod;
ans[i][j]%=mod;
}
}
}
return ans;
}
int countVowelPermutation(int n) {
vector<vector<long>> cur={{1},{1},{1},{1},{1}};
vector<vector<long>> mat={{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}};
n--;
while(n){
if(n&1) cur=mul(mat,cur);
mat=mul(mat,mat);
n=n>>1;
}
int sum=0;
for(int i=0;i<5;i++)
sum=(sum+cur[i][0])%mod;
return sum;
}
};版权声明:本文为ZHUYAN1209原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。