tzoj.4954 矩阵游戏

通过先这样再那样然后这样那样那样这样的推算得

F(n,m)=a·F(n,m-1)+b=(a^(m-1))F(n,1)+b+ab+...+(a^(m-2))b=(a^(m-1))c·F(n-1,m)+(a^(m-1))d+b+ab+...+(a^(m-2))b

记p=b+ab+...+(a^(m-2))b, x=(a^(m-1))c, y=(a^(m-1))d+p, q=y+xy+...+(x^(n-2))y

那么F(n,m)=x·F(n-1,m)+y=(x^(n-1))F(1,m)+q=(x^(n-1))(a^(m-1)+p)+q;

然后用费马小定理优化 F(n,m) = F ( n%(mod-1) , m%(mod-1) ) 

#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
void sbl(long long (&x)[2][2],long long (&y)[2][2])
{
	long long zc[2][2]={0};
	for(int i=0;i<2;++i){
		for(int j=0;j<2;++j){
			for(int k=0;k<2;++k)
				zc[i][j]=(zc[i][j]+x[i][k]*y[k][j])%MOD;
		}
	}
	for(int i=0;i<2;++i)
		for(int j=0;j<2;++j)
			x[i][j]=zc[i][j];
}
int main()
{
	long long i,j,n=0,l,m=0,a,b,c,d,fn1,fnm,mm,nn;
	string s1,s2;
	cin>>s1>>s2;
	cin>>a>>b>>c>>d;
	long long A[2][2]={1,1,0,0},B[2][2]={a,0,b,1},C[2][2]={c,0,d,1},D[2][2]={1,0,0,1};
	if(a==1)
	{
		long long len=s1.size();
		for(i=0;i<len;++i)
		{
			n=(n*10+s1[i]-'0')%MOD;
		}
	}
	else
	{
		long long len=s1.size();
		for(i=0;i<len;++i)
		{
			n=(n*10+s1[i]-'0')%(MOD-1);
		}
	}
	if(c==1)
	{
		long long len=s2.size();
		for(i=0;i<len;++i)
		{
			m=(m*10+s2[i]-'0')%MOD;
		}
	}
	else
	{
		long long len=s2.size();
		for(i=0;i<len;++i)
		{
			m=(m*10+s2[i]-'0')%(MOD-1);
		}
	}		
	m--,n--;
	while(m)
	{
		if(m%2)
		{
			sbl(D,B);
		}
		m/=2;
		sbl(B,B);
	}
	long long zc1[2][2];
	memcpy(zc1,D,sizeof(D));
	sbl(D,C);
	
	
	while(n)
	{
		if(n%2) sbl(A,D);
		n/=2;
		sbl(D,D);		
	}
	sbl(A,zc1);
	printf("%lld\n",A[0][0]);
	
	 
	
	return 0;
}

费马欧几里得什么的最烦了,为什么这么抽象啊受不了(小声叭叭)算了不敢叭叭

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值