BZOJ3240 [Noi2013]矩阵游戏 矩阵 快速幂 卡常

原文链接http://www.cnblogs.com/zhouzhendong/p/8084891.html


 

题目传送门 - BZOJ3240


 

题意概括

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)
递推式中a,b,c,d都是给定的常数。

求F[n][m]

1<=N,M<=10^1000 000,a<=a,b,c,d<=10^9


 

题解

  可以看这题—>差不多的题目,是这题的加难版: BZOJ3286


代码

#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long LL;
const LL mod=1000000007;
bool isd(char ch){return '0'<=ch&&ch<='9';}
struct BigInt{
	static const int MaxL=1000005;
	int len,v[MaxL];
	void print(){
		for (int i=len;i>=1;i--)
			printf("%d",v[i]);
	}
	void read(){
		len=0;
		char ch=getchar();
		while (!isd(ch))
			ch=getchar();
		while (isd(ch))
			v[++len]=ch-48,ch=getchar();
		for (int i=1;i<=len/2;i++)
			swap(v[i],v[len+1-i]);
	}
	void minus(int x){
		v[1]-=x;
		for (int i=1;i<=len&&v[i]<0;i++)
			v[i+1]--,v[i]+=10;
		while (!v[len])
			len--;
	}
}n,m;
LL a,b,c,d;
void CLZ(LL &x){x=(x%mod+mod)%mod;}
struct Mat{
	LL v00,v01,v10,v11;
	Mat (){}
	Mat (int x){
		v00=v01=v10=v11=0;
		if (x==1)
			v00=v11=1;
	}
}Mx(0),My(0),M,Ma(0),Mb;
Mat operator * (Mat a,Mat b){
	Mat ans;
	ans.v00=(a.v00*b.v00+a.v01*b.v10)%mod;
	ans.v01=(a.v00*b.v01+a.v01*b.v11)%mod;
	ans.v10=(a.v10*b.v00+a.v11*b.v10)%mod;
	ans.v11=(a.v10*b.v01+a.v11*b.v11)%mod;
	return ans;
}
Mat MatPow(Mat x,int y){
	Mat ans(1);
	for (;y;y>>=1,x=x*x)
		if (y&1)
			ans=ans*x;
	return ans;
}
Mat MatPow(Mat x,int *v,int len){
	Mat ans(1),M[10];
	M[0]=Mat(1);
	for (int i=1;i<=9;i++)
		M[i]=M[i-1]*x;
	for (int i=len;i>=1;i--)
		ans=MatPow(ans,10)*M[v[i]];
	return ans;
}
int main(){
	n.read(),m.read();
	m.minus(1),n.minus(1);
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
	CLZ(a),CLZ(b),CLZ(c),CLZ(d);
	Ma.v00=1,Ma.v01=1;
	Mx.v00=a,Mx.v10=b;
	Mx.v01=0,Mx.v11=1;
	My.v00=c,My.v10=d;
	My.v01=0,My.v11=1;
	M=MatPow(Mx,m.v,m.len);
	Mb=Ma*MatPow(M*My,n.v,n.len)*M;
	printf("%lld\n",Mb.v00);
	return 0;
}

  

 

posted @ 2017-12-22 10:43  zzd233  阅读(262)  评论(0编辑  收藏  举报