OJ试题记录

超级蛙跳

Description

有一个超级运动员利用台阶练习蛙跳,每次可以跳一阶、二阶或者三阶,求该运动员跳上n阶的台阶,可能有多少种跳法。

Input

一个正整数n(1<=n<=1E18)表示台阶的阶数。

Output

一个非负整数,表示该运动员跳上n阶台阶的跳法对2021取模的结果。

Sample Input 1 

1

Sample Output 1

1

Sample Input 2 

2

Sample Output 2

2

Sample Input 3 

3

Sample Output 3

4

为了优化dp,采用了矩阵的快速幂算法。

#include<stdio.h>
#include<stdlib.h>
#include<cstring>
typedef long long ll;
const ll maxn = 1e18 + 10;
const int mod = 2021;
struct Mat {
	ll m[3][3];
}ans,res;//ans为结果矩阵,a为输入矩阵
Mat Mul(Mat a, Mat b, int n) {//计算矩阵a乘矩阵b,n为矩阵的大小
	Mat c;//临时矩阵c
	memset(c.m, 0, sizeof(c.m));
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			for (int k = 0; k < n; k++)
				c.m[i][j] = (c.m[i][j] + (a.m[i][k] * b.m[k][j]) % mod) % mod;
	return c;
}
Mat _power(Mat a, ll b, int n) {//计算a^b,n为矩阵的大小
	for (int i = 0; i < n; i++)//构造单位矩阵
		res.m[i][i] = 1;
	while (b) {
		if (b & 1)
			res = Mul(res, a, n);
		a = Mul(a, a, n);
		b >>= 1;
	}
	return res;
}
int main()
{
	ll N;
	scanf("%ld", &N);
	if (N == 1 || N == 2 || N == 3){
		if (N == 1) printf("1");
		else if (N == 2)printf("2");
		else if (N == 3)printf("4");
		return 0;
	}
	else
	{
		ans.m[0][0] = 1;
		ans.m[0][1] = 1;
		ans.m[0][2] = 1;
		ans.m[1][0] = 1;
		ans.m[1][1] = 0;
		ans.m[1][2] = 0;
		ans.m[2][0] = 0;
		ans.m[2][1] = 1;
		ans.m[2][2] = 0;
		Mat result = _power(ans, N - 3, 3);
		ll Out = (((result.m[0][0] * 4) % mod + (result.m[0][1] * 2) % mod) % mod + (result.m[0][2] * 1)) % mod;
		printf("%ld", Out);
		return 0;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值