B - M斐波那契数列(矩阵快速幂,费马小定理)

题源

这道题需要用到矩阵快速幂和费马小定理,刚开始我一根筋,以为是对f【n】用矩阵快速幂,怎么也想不出该左乘或右乘哪个矩阵,后来上网找的提示,才知道是对指数用矩阵快速幂,同时使用费马小定理,因为f【n】 = a ^ i * b ^ j;

我说的不好,具体看代码吧(虽然代码也不好)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
struct mat
{
	ll a[4][4];
	mat() {
		a[1][1] = 0;
		a[1][2] = a[2][1] = a[2][2] = 1;
	}
	mat(bool f)
	{
		memset(a, 0, sizeof(a));
	}
};
void put(mat x)
{
	for (int i = 1; i <= 2; i++)
	{
		for (int j = 1; j <= 2; j++)
		{
			cout << x.a[i][j] << " ";
		}
		cout << endl;
	}
}
mat unit;
mat operator * (mat x, mat y)
{
	mat ans(true);
	for (int i = 1; i <= 2; i++)
	{
		for (int j = 1; j <= 2; j++)
		{
			for (int k = 1; k <= 2; k++)
			{
				ans.a[i][j] += ((x.a[i][k] * y.a[k][j]) % (MOD-1));
			}
		}
	}
	return ans;
}
mat mpow(mat x, ll p)
{
	mat ans = unit;
	while (p) {
		if (p & 1) ans = ans * x;
		x = x * x;
		p >>= 1;
	}
	//put(ans);
	return ans;
}
ll qpow(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1) ans = (ans * x) % MOD;
		x = (x * x) % MOD;
		y >>= 1;
	}
	return ans;
}
mat get_AB(ll n,mat tmp)
{
	//cout << " n " << n << endl;
	mat A, ans;
	ans = mpow(A, n);
	ans = tmp * ans;
	//put(ans);
	return ans;
}
int main()
{
	memset(unit.a, 0, sizeof(unit.a));
	unit.a[1][1] = unit.a[2][2] = 1;
	unit.a[1][2] = unit.a[2][1] = 0;
	//put(unit);
	ll a, b, n;
	while (cin >> a >> b >> n)
	{
		if (n <= 2)
		{
			if (n<=1)
				n ? cout << b << endl : cout << a << endl;
			else cout << (a * b) % (MOD - 1) << endl;
		}
		else {
			mat tmp;
			tmp.a[1][1] = 0; tmp.a[1][2] = 1;
			tmp.a[2][1] = 1; tmp.a[2][2] = 1;
			mat ab = get_AB(n - 2, tmp);
			ll na = ab.a[1][2];
			ll nb = ab.a[2][2];
			//cout << na << " " <<  nb << endl;
			ll ans = (qpow(a, na) * qpow(b, nb)) % MOD;
			cout << ans << endl;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值