2019南昌网络赛H The Nth Item 矩阵快速幂

网址:https://nanti.jisuanke.com/t/41355

题意:

求$Q$次$F(n)mod998244353$的所有值的异或,$F(n)$由递推公式给出,且必须在线,$Q \leq 1e7$。

题解:

看到形如$F(n)=a*F(n-1)+b*F(n-2)$的式子,就是矩阵快速幂的套路,直接矩阵快速幂求出来,然后按照题意模拟即可。矩阵快速幂和数的快速幂同理,只不过刚开始的$res=1$换成单位矩阵即可。实测$1e7$会超时,加上记忆化即可通过。

AC代码:

#include <bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int MAXN = 1e7 + 5;
unordered_map<int, ll>mp;
struct Mat
{
	ll m[2][2];
};
Mat mul(Mat a, Mat b)
{
	Mat tmp;
	memset(tmp.m, 0, sizeof(tmp.m));
	tmp.m[0][0] = (a.m[0][0] * b.m[0][0] % mod + a.m[0][1] * b.m[1][0] % mod) % mod;
	tmp.m[0][1] = (a.m[0][0] * b.m[0][1] % mod + a.m[0][1] * b.m[1][1] % mod) % mod;
	tmp.m[1][0] = (a.m[1][0] * b.m[0][0] % mod + a.m[1][1] * b.m[1][0] % mod) % mod;
	tmp.m[1][1] = (a.m[1][0] * b.m[0][1] % mod + a.m[1][1] * b.m[1][1] % mod) % mod;
	return tmp;
}
Mat inv(Mat a,ll n)
{
	Mat res;
	memset(res.m, 0, sizeof(res.m));
	for (int i = 0; i < 2; ++i)
		res.m[i][i] = 1;
	while (n)
	{
		if (n & 1)
			res = mul(res, a);
		a = mul(a, a);
		n >>= 1;
	}
	return res;
}
Mat beg, b, mtmp;
void init()
{
	memset(beg.m, 0, sizeof(beg.m));
	beg.m[0][0] = 1;
	b.m[0][0] = 3;
	b.m[0][1] = 1;
	b.m[1][0] = 2;
}
int main()
{
	ll q, n, ans = 0;
	init();
	scanf("%lld%lld", &q, &n);
	for (int i = 1; i <= q; ++i)
	{
		ll tmp;
		if (!mp.count(n))
		{
			mtmp = mul(beg, inv(b, n - 1));
			tmp = mtmp.m[0][0] % mod;
			mp[n] = tmp;
		}
		else
			tmp = mp[n];
		ans ^= tmp;
		tmp %= mod;
		n ^= tmp * tmp;
	}
	printf("%lld\n", ans);
	return 0;
}

  

 

posted @ 2019-09-08 23:32  Aya_Uchida  阅读(360)  评论(0编辑  收藏  举报