牛客网-递推数列【矩阵快速幂】进化版斐波那契

在这里插入图片描述
乍一看直接模拟,暴力递推,索性NK的数据比较水,过起来很容易

#include<iostream>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
using namespace std;

#define ll int
#define MAX 250
#define inf 10000000
#define mod 10000

int main() {
	ll a0, a1, p, q, k;
	while (cin >> a0 >> a1 >> p >> q >> k) {
		ll cnt = 2, res = 0;
		if (k == 0)cout << a0 << endl;
		else if (k == 1)cout << a1 << endl;
		else {
			while (cnt <= k) {
				res = (q * a0 % mod + p * a1 % mod) % mod;
				a0 = a1, a1 = res; cnt++;
			}
		}
		cout << res << endl;
	}
}

但是这种题直接递推一般是过不了的出题人比较憨除外,这种类似于斐波那契数列的问题,一般都可以高效的转化为矩阵快速幂进行计算,一个详细教程

对公式
a n = p a ( n 1 ) + q a ( n 2 ) an=p*a(n-1) + q*a(n-2)
我们可以将他写作
在这里插入图片描述
在这里插入图片描述
这样的话我们进行和正常斐波那契数列一样的递推,就能得出(详细步骤见上面链接的教程)

在这里插入图片描述

#include<iostream>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
using namespace std;

#define ll int
#define MAX 250
#define inf 10000000
#define mod 10000

struct mat {
	ll a[2][2];
	mat operator * (mat m) {
		mat res;
		for (int i = 0; i < 2; i++)for (int j = 0; j < 2; j++)res.a[i][j] = 0;
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 2; j++)
				for (int k = 0; k < 2; k++)
					res.a[i][j] = (res.a[i][j] + a[i][k] * m.a[k][j]) % mod;
		return res;
	}
};

mat quickPow(mat a, int k) {
	mat res;//对角矩阵
	res.a[0][0] = res.a[1][1] = 1; res.a[0][1] = res.a[1][0] = 0;
	while (k > 0) {
		if (k & 1) res = res * a;
		a = a * a; k >>= 1;
	}
	return res;
}

int main() {
	ll a0, a1, p, q, k;
	while (cin >> a0 >> a1 >> p >> q >> k) {
		ll cnt = 2, ans = 0;
		if (k == 0)cout << a0 << endl;
		else if (k == 1)cout << a1 << endl;
		mat a; a.a[0][0] = p, a.a[0][1] = q, a.a[1][0] = 1, a.a[1][1] = 0;
		mat res = quickPow(a, k - 1);
		ans = ((res.a[0][0] * a1) % mod + (res.a[0][1] * a0) % mod) % mod;
		cout << ans << endl;
	}
}
发布了269 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105625010