题目
数列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的前n项和s[n]的快速求法(不考虑高精度).
思路
仿照之前的思路,
考虑1×3的矩阵
∣
f
[
n
−
1
]
f
[
n
−
2
]
s
[
n
−
2
]
∣
\begin{vmatrix}f[n-1]&f[n-2]&s[n-2]\end{vmatrix}
∣∣f[n−1]f[n−2]s[n−2]∣∣
我们希望通过乘以一个3×3的矩阵A,得到1×3的矩阵:
∣
f
[
n
]
f
[
n
−
1
]
s
[
n
−
1
]
∣
\begin{vmatrix}f[n]&f[n-1]&s[n-1]\end{vmatrix}
∣∣f[n]f[n−1]s[n−1]∣∣
=
~=~
=
∣
f
[
n
−
1
]
+
f
[
n
−
2
]
f
[
n
−
1
]
s
[
n
−
2
]
+
f
[
n
−
1
]
∣
\begin{vmatrix}f[n-1]+f[n-2]&f[n-1]&s[n-2]+f[n-1]\end{vmatrix}
∣∣f[n−1]+f[n−2]f[n−1]s[n−2]+f[n−1]∣∣
容易得到这个3×3的转移矩阵是:
∣
1
1
1
1
0
0
0
0
1
∣
\begin{vmatrix}1&1&1\\1&0&0\\0&0&1\end{vmatrix}
∣∣∣∣∣∣110100101∣∣∣∣∣∣
C o d e Code Code
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const long long mod=1000000007;
long long n,a[4][4],ans[4][4];
long long fd[4][4];
void jzcf(int m)
{
long long c[4][4];
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
c[i][j]=0;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
for(int k=1; k<=m; k++)
c[i][j]=(c[i][j]+(a[i][k]*ans[k][j])%mod)%mod;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
ans[i][j]=c[i][j];
}
void jzcf2(int m)
{
long long c[4][4];
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
c[i][j]=0;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
for(int k=1; k<=m; k++)
c[i][j]=(c[i][j]+(a[i][k]*a[k][j])%mod)%mod;
for(int i=1; i<=m; i++)
for(int j=1; j<=m; j++)
a[i][j]=c[i][j];
}
void jzcf3()
{
long long c[4][4];
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++)
c[i][j]=0;
for(int i=1; i<=1; i++)
for(int j=1; j<=3; j++)
for(int k=1; k<=3; k++)
c[i][j]=(c[i][j]+(fd[i][k]*ans[k][j])%mod)%mod;
for(int i=1; i<=1; i++)
for(int j=1; j<=3; j++)
fd[i][j]=c[i][j];
}
void ksm(long long k)
{
for(int i=1; i<=3; i++)
ans[i][i]=1;
while(k!=0)
{
if(k&1)
jzcf(3);
jzcf2(3);
k>>=1;
}
}
int main()
{
cin>>n;
if(n==1)
{
cout<<1;
return 0;
}
a[1][1]=1,a[1][2]=1,a[1][3]=1;
a[2][1]=1,a[2][2]=0,a[2][3]=0;
a[3][1]=0,a[3][2]=0,a[3][3]=1;
fd[1][1]=1,fd[1][2]=1,fd[1][3]=1;
ksm(n-1);
jzcf3();
cout<<fd[1][3];
return 0;
}
//矩阵快速幂里面的k是int,但是要用long long,不然会爆,n都开了long long了。