P1397 [NOI2013] 矩阵游戏(矩阵乘法&欧拉定理)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1397 [NOI2013] 矩阵游戏(矩阵乘法&欧拉定理)相关的知识,希望对你有一定的参考价值。

P1397 [NOI2013] 矩阵游戏(矩阵乘法&欧拉定理)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e6+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define db double
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n)
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 

template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y)
	if(x<y) x=y;

template <typename T>
void cmn(T &x,T y)
	if(x>y) x=y;

struct mtx
	ll a[3][3];
	int r,c;
	mtx(int rr,int cc,int p=0)
		r=rr,c=cc;
		mst(a,0);
		if(p==1) for(int i=1;i<=rr;i++) a[i][i]=1;
	
	mtx operator *(const mtx &b)const
		mtx m(r,b.c);
			for(int i=1;i<=r;i++)
			for(int j=1;j<=m.c;j++)
				for(int k=1;k<=c;k++)
			m.a[i][j]=(m.a[i][j]+1LL*a[i][k]*b.a[k][j]%mod)%mod;
		return m;
	
	mtx operator ^(int n)const
		mtx ans(r,c,1),x=*this;
		while(n)
		if(n&1) ans=ans*x;
		x=x*x;
		n>>=1;
		
		return ans;
	
;
char s[N],t[N];
int n,m,a,b,c,d;
int main()
	mtx A(2,2),B(2,2),C(2,2);
	scanf("%s%s%d%d%d%d",s,t,&a,&b,&c,&d);
	int l = strlen(s);
	int mo = (a==1)?mod:mod-1;
	for(int i=0;i<l;i++)
		n = (n*10LL + (s[i]-'0')) %mo; 
	l = strlen(t);
	for(int i=0;i<l;i++)
		m = (m*10LL + (t[i]-'0')) %mo; 
	A.a[1][1] = a,A.a[1][2] = 0;
	A.a[2][1] = b,A.a[2][2] = 1;
	B.a[1][1] = c,B.a[1][2] = 0;
	B.a[2][1] = d,B.a[2][2] = 1;	
	A=A^(m-1);
	C = A;
	A=A*B;
	A=A^(n-1);
	A=A*C;
	mtx D(1,2);
	D.a[1][1] = D.a[1][2] = 1;
	D=D*A;
	printf("%d\\n",D.a[1][1]);
	return 0;



上面的做法过不了UOJ的数据。

所以正解直接对大整数跑10进制的快速幂。

#include<bits/stdc++.h>
using namespace std;
const int N=1000005,P=1e9+7;
char n[N],m[N];int nl,ml,a,b,c,d;
struct detint d[2][2];I,p,q;
det operator*(det x,det y)
	det r=;
	for(int i=0;i<2;i++)
		for(int j=0;j<2;j++)
			for(int k=0;k<2;k++)
				r.d[i][j]=(1ll*x.d[i][k]*y.d[k][j]+r.d[i][j])%P;
	return r;

void pw(char*x,int l)
	for(int i=l-1;~i;i--)
		det k=p;
		for(char j='0';j<x[i];j++)I=I*k;
		for(int j=0;j<9;j++)p=p*k;
	

int main()
	scanf("%s%s%d%d%d%d",n,m,&a,&b,&c,&d);
	nl=strlen(n);
	ml=strlen(m);
	n[nl-1]--;
	m[ml-1]--;
	for(int i=nl-1;n[i]<'0';i--)
		n[i]+=10,n[i-1]--;
	for(int i=ml-1;m[i]<'0';i--)
		m[i]+=10,m[i-1]--;
	I.d[0][0]=1;
	I.d[1][1]=1;
	p.d[0][0]=a;
	p.d[0][1]=b;
	p.d[1][1]=1;
	q.d[0][0]=c;
	q.d[0][1]=d;
	q.d[1][1]=1;
	pw(m,ml);
	p=q*I;
	pw(n,nl);
	cout<<(I.d[0][0]+I.d[0][1])%P;
	return 0;

以上是关于P1397 [NOI2013] 矩阵游戏(矩阵乘法&欧拉定理)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3240 && 洛谷P1397矩阵游戏[NOI2013](矩阵乘法+卡常)

洛谷P1397 [NOI2013]矩阵游戏

bzoj3240 Noi2013—矩阵游戏

P1224 [NOI2013] 向量内积(矩阵乘法&随机化)

bzoj 3240: [Noi2013]矩阵游戏

bzoj3240: [Noi2013]矩阵游戏