裴波拉契数列II(矩阵乘法练习题一)

Description

形如 1 1 2 3 5 8 13 21 34 55 89 144…的数列,求裴波拉契数列的第n项。

Input

1<n< 2 31 2^{31} 231

Output

一个数为裴波拉契数列的第n项mod 10000;

Sample Input

123456789

Sample Output

4514

思路:
一看 N N N的大小,暴力 O ( n ) O(n) O(n)递推一定会炸掉,
我们考虑采用一种叫矩阵乘法的加速优化。
这里就不介绍他的概念了戳这里

矩阵乘法:
考虑一个1×2的矩阵[ f n − 2 , f n − 1 f_{n-2},f_{n-1} fn2,fn1]
根据fibonacci数列递推公式,我们希望通过乘以一个2×2的矩阵,
得到矩阵【f[n-1],f[n]】=【f[n-1],f[n-1]+f[n-2]】很容易构造出这个2×2矩阵A,即:

在这里插入图片描述

所以,有【f[1],f[2]】×A=【f[2],f[3]】
又因为矩阵乘法满足结合律,故有:
【f[1],f[2]】× A n − 1 A^{n-1} An1=【f[n],f[n+1]】
这个矩阵的第一个元素即为所求。

#include <cstring>
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const ll Mod = 1e4;
struct node
{
	ll x, y, a[40][40];
} A, B, C;
ll n;
node operator *(node x, node y) //矩阵乘法模板
{
	node ans;
	memset(ans.a, 0, sizeof(ans.a));
	ans.x = x.x, ans.y = y.y;
	for(ll k = 1; k <= x.y; k++)
	 for(ll i = 1; i <= x.x; i++)
	  for(ll j = 1; j <= y.y; j++)
	  	ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j] % Mod) % Mod;
	return ans;

}
void ksm(ll k)  //计算A(矩阵)^n-1
{
	if(k == 1) {C = B; return ;}
	ksm(k >> 1);
	C = C * C;
	if(k & 1) C = C * B;
}
int main()
{
	scanf("%lld", &n);
	if(n < 3) {printf("1\n"); return 0;}
	A.a[1][2] = A.a[1][1] = 1, A.x = 1; A.y = 2; //递推矩阵
	B.a[1][2]= B.a[2][1] = B.a[2][2] = 1, B.x = 2, B.y = 2;  //构造单位矩阵
	ksm(n - 1), C = A * C;
	printf("%lld", C.a[1][1] % Mod); 
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值