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; }