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

时间:2022-12-17 10:08:02

原文链接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;
}