码迷,mamicode.com
首页 > 其他好文 > 详细

【bzoj3240】 Noi2013—矩阵游戏

时间:2016-09-29 21:43:45      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:

http://www.lydsy.com/JudgeOnline/problem.php?id=3240 (题目链接)

题意

  F[1][1]=1
  F[i,j]=a*F[i][j-1]+b (j!=1)
  F[i,1]=c*F[i-1][m]+d (i!=1)

  求解F[n][m],a,b,c,d为常数。

Solution

  原来费马小定理对于矩阵乘法同样适用。。设a为一矩阵,p为质数则:

技术分享

  正好这里的模数1000000007为质数,那么把n,m模上(p-1)后进行矩阵快速幂即可。用来优化的矩阵很好构造,记得特判a和c等于1的情况。

  注意如果重载了*,不要弄错了乘法的顺序,因为矩阵乘法是不满足交换律的。

代码

// bzoj3240
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
#define MOD 1000000007
#define inf 2147483640
#define LL long long
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;

char s1[1000010],s2[1000010];
LL n,m,a,b,c,d;

struct data {
	LL x[3][3];
	friend data operator * (const data &a,const data &b) {
		data tmp;tmp.x[0][1]=tmp.x[0][2]=tmp.x[0][0]=tmp.x[1][0]=tmp.x[2][0]=0;
		for (int i=1;i<=2;i++)
			for (int j=1;j<=2;j++) {
				tmp.x[i][j]=0;
				for (int k=1;k<=2;k++) tmp.x[i][j]=(tmp.x[i][j]+a.x[i][k]*b.x[k][j])%MOD;
			}
		return tmp;
	}
}A,B,T,ans,res;
void power(data a,int b) {
	ans.x[1][1]=1;ans.x[1][2]=0;ans.x[2][1]=0;ans.x[2][2]=1;
	while (b) {
		if (b&1) ans=a*ans;
		b>>=1;
		a=a*a;
	}
}
int main() {
	scanf("%s%s%lld%lld%lld%lld",s1,s2,&a,&b,&c,&d);
	A.x[1][1]=a;A.x[1][2]=0;A.x[2][1]=b;A.x[2][2]=1;
	B.x[1][1]=c;B.x[1][2]=0;B.x[2][1]=d;B.x[2][2]=1;
	T.x[1][1]=1;T.x[1][2]=1;T.x[2][1]=T.x[2][2]=0;
	LL P=MOD-1;
	if (a==1 && c==1) P=MOD;
	int l=strlen(s1);
	for (int i=0;i<l;i++) n=(n*10+s1[i]-‘0‘)%P;
	l=strlen(s2);
	for (int i=0;i<l;i++) m=(m*10+s2[i]-‘0‘)%P;
	power(A,m-1);
	for (int i=1;i<=2;i++)
		for (int j=1;j<=2;j++) A.x[i][j]=res.x[i][j]=ans.x[i][j];
	A=A*B;
	power(A,n-1);
	res=ans*res;
	res=T*res;
	printf("%lld",res.x[1][1]);
	return 0;
}

  

【bzoj3240】 Noi2013—矩阵游戏

标签:

原文地址:http://www.cnblogs.com/MashiroSky/p/5921072.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!