矩阵快速幂优化递推

广义斐波那契数列

题目描述

广义的斐波那契数列是指形如 \(a_n=p\times a_{n-1}+q\times a_{n-2}\) 的数列。

今给定数列的两系数 \(p\)\(q\),以及数列的最前两项 \(a_1\) 和 $ a_2$,另给出两个整数 \(n\)\(m\),试求数列的第 \(n\)\(a_n\)\(m\) 取模后的结果。

输入格式

输入包含一行六个整数,\(p,q,a_1,a_2,n,m\)

输出格式

输出包含一行一个整数表示答案。

样例 #1

样例输入 #1

1 1 1 1 10 7

样例输出 #1

6

提示

数列第 $10 $项是 \(55\)\(55 \bmod 7 = 6\)

【数据范围】
对于 \(100\%\) 的数据,\(p,q,a_1,a_2 \in [0,2^{31}-1]\)\(1\le n,m \le 2^{31}-1\)


#include <bits/stdc++.h>
using namespace std;
int p, q, a1, a2, n, mo;

struct matrix {
	int n, m;
	int z[3][3];
	matrix() {
		memset(z, 0, sizeof z);
	}

} _, A;

matrix operator*(const matrix &x, const matrix &y) {
	matrix z;
	z.n = x.n;
	z.m = y.m;

	for (int i = 1; i <= z.n; i++)
		for (int k = 1; k <= x.m; k++)
			for (int j = 1; j <= z.m; j++)
				z.z[i][j] = (z.z[i][j] + 1ll * x.z[i][k] * y.z[k][j] % mo) % mo;

	return z;
}

int main() {

	scanf("%d%d%d%d%d%d", &p, &q, &a1, &a2, &n, &mo);
	p %= mo, q %= mo;
	if (n == 1)printf("%d", a1 % mo), exit(0);
	if (n == 2)printf("%d", a2 % mo), exit(0);

	_.n = 2;
	_.m = 1;
	_.z[1][1] = a2;
	_.z[2][1] = a1;

	A.n = 2, A.m = 2;
	A.z[1][1] = p, A.z[1][2] = q;
	A.z[2][1] = 1, A.z[2][2] = 0;

	int mi = n-2;
	for (; mi; mi >>= 1, A = A * A)
		if (mi & 1)_ = A * _;//左乘:注意A和_位置不能换

	printf("%d", _.z[1][1]);

	return 0;
}
posted @ 2022-11-20 11:07  AC7  阅读(47)  评论(0)    收藏  举报