P5110 块速递推

题意

显然矩乘,不过需要\(O(1)\)快速幂。

预处理\([0,t]\)\(t=\sqrt{p}\))次幂的所有矩阵,之后预处理\([t^1,t^t]\)的所有矩阵,这样对于一个\(k\),我们要的矩阵就是:
\(a^{k\%p}*a^{k/p}\)

code:

#include<bits/stdc++.h>
using namespace std;
#define re register
typedef unsigned long long ull;
const ull mod=1e9+7; 
ull T,SA,SB,SC,ans;
inline void init(){scanf("%llu%llu%llu",&SA,&SB,&SC);}
inline ull read()
{	
    SA^=SA<<32,SA^=SA>>13,SA^=SA<<1;
    re unsigned long long t=SA;
	SA=SB,SB=SC,SC^=t^SA;
	return SC%(mod-1);//warning!!!
}
struct Mat
{
	ull a[3][3];
	Mat(){memset(a,0,sizeof(a));}
	ull* operator[](const int i){return a[i];}
	Mat operator*(const Mat x)
	{
		Mat res;
		for(re int i=1;i<=2;i++)
			for(re int j=1;j<=2;j++)
				for(re int k=1;k<=2;k++)
					res[i][j]=(res[i][j]+a[i][k]*x.a[k][j])%mod;
		return res;
	}
	inline void idx(){for(re int i=1;i<=2;i++)a[i][i]=1;}
}pw1[32010],pw2[32010];
int main()
{
	pw1[0].idx();
	pw1[1][1][1]=233,pw1[1][2][1]=666,pw1[1][1][2]=1;
	for(re int i=1;i<=32000;i++)pw1[i]=pw1[i-1]*pw1[1];
	pw2[0].idx();
	pw2[1]=pw1[32000];
	for(re int i=1;i<=32000;i++)pw2[i]=pw2[i-1]*pw2[1];
	scanf("%llu",&T);
	init();
	while(T--)
	{
		re int k=read()-1;
		if(k==-1)continue;
		Mat res=pw1[k%32000]*pw2[k/32000];
		ans^=res[1][1]%mod;
	}
	printf("%llu",ans);
	return 0;
}
posted @ 2019-12-21 17:13  nofind  阅读(89)  评论(0编辑  收藏  举报