sdnu1085.爬楼梯再加强版(矩阵快速幂)
Description
WZ是个蛋痛的人,总是喜欢琢磨蛋痛的事,比如他最近想知道上楼梯总共有多少种方式。已知他一步可以迈一阶、两阶或者三阶,现在给你楼梯的阶数,让你计算总共有多少种方式。
Input
输入有多组数据,每组数据占一行,表示楼梯的阶数。(1<=N<=100,000,000,000)
Output
对于每组数据,输出一行,表示上楼方式的总数 % 1000000007。
Sample Input
1
2
Sample Output
1
2
矩阵快速幂 讲解+推导
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3;
const int MOD=1000000007;
struct mat
{
ll a[N][N];
};
mat mat_mul(mat x,mat y)
{
mat res;
memset(res.a,0,sizeof(res.a));
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
for(int k=0; k<3; k++)
res.a[i][j]=(res.a[i][j]+(x.a[i][k]*y.a[k][j])%MOD)%MOD;
return res;
}
long long mat_pow(ll n)
{
mat c,res;
memset(c.a,0,sizeof(c.a));
c.a[0][0]=c.a[0][1]=c.a[0][2]=1;
c.a[1][0]=1;
c.a[2][1]=1;
memset(res.a,0,sizeof(res.a));
for(int i=0; i<3; i++)
res.a[i][i]=1;
while(n)
{
if(n&1)
res=mat_mul(res,c);
c=mat_mul(c,c);
n=n>>1;
}
return ((4*res.a[0][0])%MOD+(2*res.a[0][1])%MOD+res.a[0][2]%MOD)%MOD;///4 2 1分别是前三项
}
int main()
{
long long n;
while(scanf("%lld",&n)!=EOF)
{
if(n==1)
cout<<1<<'\n';
else if(n==2)
cout<<2<<'\n';
else if(n==3)
cout<<4<<'\n';
else
{
long long ans=mat_pow(n-3);
cout<<ans<<'\n';
}
}
return 0;
}