HLG-1126(矩阵乘法+快速幂)

Final Destination II
Time Limit: 1000 MS    Memory Limit: 65536 K
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.

题意:可以走1步或2步或3步,求走到距离n步可以有多少走法。

思路:通过矩阵相乘来递推优化,根据之前的状态递推后面的状态。如该题当前n步数等于到n-1步、n-2步、n-3步之和。

构造矩阵:

1 1 1        a(n-1) 0 0

1 0 0   X  a(n-2) 0 0

0 1 0        a(n-3) 0 0

每次相乘都将每位置状态向后移一次。

#include<stdio.h>
#include<string.h>
#define mod 1000000007
long long stairs[3][3];
void multy(long long a[][3],long long b[][3])//矩阵的乘法
{
    long long i, j, k;
    long long c[3][3];
    for(i = 0; i < 3; i++)
        for(j = 0; j < 3; j++){
            c[i][j] = 0;
            for(k = 0; k < 3; k++){
                c[i][j] += ((a[i][k]%mod)*(b[k][j]%mod))%mod;
            }
        }
    for(i = 0; i < 3; i++)//将结果返回给b[][];
        for(j = 0; j < 3; j++)
            b[i][j] = c[i][j]%mod;
}
long long ultim(long long n,long long a[][3],long long b[][3])
{
    while(n)//矩阵的快速幂求法
    {
        if(n&1)
            multy(a,b);
        multy(a,a);
        n/=2;
    }
    return b[0][0];
}
int main()
{
    long long n,k=1,t;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        memset(stairs,0,sizeof(stairs));
        stairs[0][0]=4;stairs[1][0]=2;stairs[2][0]=1;
        long long coeff[3][3]={1,1,1,1,0,0,0,1,0};
        //multy(coeff,coeff);
        printf("Case %lld:\n",k++);
        if(n==0)
            printf("1\n");
        else if(n == 1)
            printf("1\n");
        else if(n == 2)
            printf("2\n");
        else
            printf("%lld\n",ultim(n-3,coeff,stairs));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值