Final Destination II | ||||||
| ||||||
Description | ||||||
JiaoZhu likes going on adventure! One day, he walks into a big castle, and there is an unique stairway. JiaoZhu finds a board ,it says “The one who want to go upstairs only can go three steps the most once, meaning that you can go 1 or 2 or 3 steps once!”. Now, we have a problem, can you tell me the number of ways to go to the destination? If you can’t ,death is the only choice。 In the beginning, you are in the 0th step. | ||||||
Input | ||||||
First input a integer T(T<50), represent the number of case. Each case ,the input will consist only a positive integer n (0<=n<=1000000000), represent the nth steps you want to go to.. | ||||||
Output | ||||||
Order the sample output format to output. Line 1,print the Case k. Line 2,print one integer represent the number of ways to go to nth steps.(MOD 1000000007) | ||||||
Sample Input | ||||||
2
1
2
| ||||||
Sample Output | ||||||
Case 1:
1
Case 2:
2
| ||||||
Hint | ||||||
When n=2,you can go one step once to go to 2th ,or go 2 steps once to 2th,so the answer is 2. | ||||||
Author | ||||||
齐达拉图 |
分析:
一道很简单的递推题目,主要是N特别大,直接跑o(N)也是一样会超时。所以我们利用公式+矩阵快速幂就能够优化时间复杂度,尤其在N特别大的时候,优化的越明显。
有关矩阵快速幂的学习大家可以去POJ 做一下3070 这里我提供题解:http://blog.csdn.net/mengxiang000000/article/details/50595065。
思路:
推出Fn=Fn-1+Fn-2+Fn-3。
然后老老实实的用草纸写下这样的方程式:
( | ? | ? | ? | ) | X | ( | Fn-1 | ) | = | ( | Fn | ) |
( | ? | ? | ? | ) | ( | Fn-2 | ) | ( | Fn-1 | ) | ||
( | ? | ? | ? | ) | ( | Fn-3 | ) | ( | Fn-2 | ) |
结果为:
1 1 1
1 0 0
0 1 0
然后自己拿草纸幂两次,不难发现B.mat【0】【0】就是结果。
AC代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define mod 1000000007
#define ll long long int
typedef struct Matrix
{
ll mat[3][3];
}matrix;
matrix A,B;
Matrix matrix_mul(matrix a,matrix b)//矩阵乘法
{
matrix c;
memset(c.mat,0,sizeof(c.mat));
int i,j,k;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
c.mat[i][j]%=mod;
}
}
}
return c;
}
Matrix matrix_quick_power(matrix a,int k)//矩阵快速幂0.0
{
matrix b;
memset(b.mat,0,sizeof(b.mat));
for(int i=0;i<3;i++)
b.mat[i][i]=1;//单位矩阵b
while(k)
{
if(k%2==1)
{
b=matrix_mul(a,b);
k-=1;
}
else
{
a=matrix_mul(a,a);
k/=2;
}
}
return b;
}
int main()
{
int kase=0;
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
A.mat[0][0]=1;A.mat[0][1]=1;A.mat[0][2]=1;//我们通过推论得到的矩阵A
A.mat[1][0]=1;A.mat[1][1]=0;A.mat[1][2]=0;
A.mat[2][0]=0;A.mat[2][1]=1;A.mat[2][2]=0;
B=matrix_quick_power(A,n);
printf("Case %d:\n",++kase);
printf("%d\n",B.mat[0][0]);
}
}