题意:
定义
,求
解法一(递推法)
我们设
,显然有
我们发现
,那么我们可设
,显然有
同理我们可得
,设
,显然有
于是我们就可以做到用线性复杂度求解本题了。
代码:
class Solution {
public:
const int mod=1e9+7;
int f[1000000001];
int T[1000000001];
int G[1000000001];
int F[1000000001];
int getSum(int n) {
/*边界值*/
f[0]=0;
f[1]=1;
T[1]=1;
G[1]=1;
F[1]=1;
for(int i=2;i<=n;i++){
f[i]=(f[i-1]+f[i-2])%mod;//f(2)=f(1)+f(0)=1
T[i]=(T[i-1]+f[i])%mod;//\sum_{i=1}^nf(i)
G[i]=(G[i-1]+T[i])%mod;//\sum_{i=1}^nT(i)
F[i]=(F[i-1]+G[i])%mod;//\sum_{i=1}^nG(i)
}
return F[n];
}
}; 时间复杂度: 空间复杂度:
,数组
都是
大小的,故总的空间复杂度为)
解法二(矩阵快速幂)
由
可推出
即:
由
可推出
即:
由
可推出
即:
于是我们可以构造矩阵乘法式子:
于是有
我们就可以利用矩阵快速幂算法求解了。
具体的,为了方便起见,我们
可以直接三重循环暴力求解(由于数值较小,对应的时间复杂度可视为常数)。
代码:
class Solution {
public:
/**
*
* @param n int整型
* @return int整型
*/
static const int mod=1e9+7;
struct mat{
int A[5][5];
inline mat(){
memset(A,0,sizeof A);
}
inline int* operator [] (int p){
return A[p];
}
inline mat operator * (const mat& other)const{
mat ret;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
for(int k=0;k<5;k++){
//矩阵乘法
ret.A[i][j]=(ret.A[i][j]+1ll*A[i][k]*other.A[k][j]%mod)%mod;
}
}
}
return ret;
}
};
mat ksm(mat a,int b){
//矩阵快速幂
mat ret;
for(int i=0;i<5;i++)ret.A[i][i]=1;//单位矩阵
while(b){
if(b&1){
ret=ret*a;
}
a=a*a;
b>>=1;
}
return ret;
}
int f[6];
int F[6];
int getSum(int n) {
f[0]=0,f[1]=1;
for(int i=2;i<=5;i++){
f[i]=(f[i-1]+f[i-2])%mod;
}
memset(F,0,sizeof F);
for(int p=1;p<=5;p++){
for(int i=1;i<=p;i++){
for(int j=1;j<=i;j++){
for(int k=1;k<=j;k++){
F[p]=(F[p]+f[k])%mod;//前5个直接暴力求解
}
}
}
}
if(n<=5)return F[n];
mat t;
t[0][0]=4,t[0][1]=(-5+mod)%mod,t[0][2]=1,t[0][3]=2,t[0][4]=(-1+mod)%mod;
t[1][0]=1,t[2][1]=1,t[3][2]=1,t[4][3]=1;//初始化矩阵
t=ksm(t,n-5);
int ans=0;
for(int i=0;i<5;i++){
ans=(ans+1ll*t[0][i]*F[5-i]%mod)%mod;//模拟矩阵乘法求解答案
}
return ans;
}
}; 时间复杂度: 空间复杂度:
,
为矩阵大小,程序中我们只需要保存
级别个矩阵即可,故空间复杂度为)

京公网安备 11010502036488号