吉首大学重现赛 A:SARS病毒(矩阵快速幂 + 降幂)

登录—专业IT笔试面试备考平台_牛客网

https://ac.nowcoder.com/acm/contest/992/A

这题布吉岛为啥可以降幂

P为质数, 所以对次方降幂, 取模(mod - 1)

设f[i][j][k], i表示摆到第几个位置, j中0表示A的个数为偶数, 1为奇数, k中0表示B的个数为偶数, 1为奇数。

推出递推方程, 就可以矩阵快速幂了!
f[i][0][0] = 2 * f[i - 1][0][0] + f[i - 1][0][1] + f[i - 1][1][0];
f[i][0][1] = 2 * f[i - 1][0][1] + f[i - 1][1][1] + f[i - 1][0][0];
f[i][1][0] = 2 * f[i - 1][1][0] + f[i - 1][1][1] + f[i - 1][0][0];
f[i][1][1] = 2 * f[i - 1][1][1] + f[i - 1][0][1] + f[i - 1][1][0];
系数矩阵为
2 1 1 0
1 2 0 1
1 0 2 1
0 1 1 2
#include <bits/stdc++.h>
using namespace std;
#define sz(a) ((int)(a).size())
typedef long long ll;
#define me(a, b) (memset(a, b, sizeof a))
const ll INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
 
struct M{
	ll m[5][5];
	M()
	{
		me(m, 0);
	}
};
M mul(M a, M b)
{
	M res;
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			for (int k = 0; k < 4; k++)
				res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
	return res;
}
void fpow(ll n)
{
	M a;
	for (int i = 0; i < 4; i++)
		a.m[i][i] = 1;
	M b;
	b.m[0][0] = 2, b.m[0][1] = 1, b.m[0][2] = 1;
	b.m[1][0] = 1, b.m[1][1] = 2, b.m[1][3] = 1;
	b.m[2][0] = 1, b.m[2][2] = 2, b.m[2][3] = 1;
	b.m[3][1] = 1, b.m[3][2] = 1, b.m[3][3] = 2;
	while (n)
	{
		if (n & 1)
			a = mul(a, b);
		n >>= 1;
		b = mul(b, b);
	}
	M res;
	res.m[0][0] = 2, res.m[1][0] = 1, res.m[2][0] = 1;
	res = mul(a, res);
	cout << res.m[0][0] % mod << endl;
}
int main(){
	string s;
	while (cin >> s)
	{
		ll b = 0;
		int len = sz(s);
		for (int i = 0; i < len; i++)
		{
			b = (b * 10 + s[i] - '0') % (mod - 1);
		}
		fpow(b - 1);
	}
	return 0;
}
全部评论

相关推荐

头像
11-07 01:12
重庆大学 Java
精致的小松鼠人狠话不多:签哪了哥
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务