“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛 1010 Count

“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛 1010 Count_第1张图片
思路:矩阵快速幂。推一下初始矩阵就好了

#include

#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back

using namespace std;

LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 2e5 +11;
const LL mod=123456789;
LL A[6][6]={
	{0,2,0,0,0,0},
	{1,1,0,0,0,0},
	{0,1,1,0,0,0},
	{0,0,3,1,0,0},
	{0,0,3,2,1,0},
	{0,0,1,1,1,1}
};
LL P[6];
struct uzi
{
	LL a[6][6];
	void res(){
		memset(a,0,sizeof a);
	}
};
int cnt;
uzi operator *(const uzi &x,const uzi &y){
	uzi ans;
	ans.res();
	for(int i=0;i<6;i++){
		for(int j=0;j<6;j++){
			LL mid=0;
			for(int k=0;k<6;k++){
				mid+=x.a[i][k]*y.a[k][j]%mod;
				mid%=mod;
			}
			ans.a[i][j]=mid;
		}
	}
	return ans;
}
LL POW(LL n){
	uzi ans,mid;
	ans.res();
	mid.res();
	for(int i=0;i<6;i++)ans.a[i][i]=1;
	for(int i=0;i<6;i++)for(int j=0;j<6;j++)mid.a[i][j]=A[i][j];
	while(n){
		if(n%2){
			ans=mid*ans;
		}
		mid=mid*mid;
		n/=2;
	}
	LL sum=0;
	for(int i=0;i<6;i++){
		sum=sum+P[i]*ans.a[i][0]%mod;
		sum%=mod;
	}
	return sum;
}
int main(){
	ios::sync_with_stdio(false);
	P[0]=1,P[1]=2,P[2]=27,P[3]=9,P[4]=3,P[5]=1;
	int t;
	for(cin>>t;t;t--){
		LL n;
		cin>>n;
		cout<<POW(n-1)<<endl;
	}
	return 0;
}

你可能感兴趣的:(矩阵)