题目大意:
一个n行m列的矩阵,
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)
其中:1<=n,m<=10^1000000,1<=a,b,c,d<=10^9
输出F[n][m]除以1,000,000,007的余数
如果用快速幂的话,需要把十进制数n,m转化为二进制,而n,m要用字符串来存储且极大,所以会TLE
这里使用十进制快速幂
另外,构造的矩阵只能用到第一列,因此把它们化简到两个元素即可,可以减小时间常数
具体见代码
#include
#include
#include
#define mod 1000000007
typedef long long LL;
char sn[1000005],sm[1000005];
struct juzhen
{
LL v1,v2;//矩阵化简:对于s[1][2]==0的矩阵,只保留s[1][1],s[2][1];不需要Z矩阵
};
juzhen I;//单位矩阵
juzhen cheng(juzhen a,juzhen b)
{
juzhen res;
res.v1=(a.v1*b.v1)%mod;
res.v2=(a.v2*b.v1+b.v2)%mod;
return res;
}
juzhen ksm(juzhen a,int n)
{
juzhen res;
if(n==0) return I;
if(n==1) return a;
res=ksm(a,n/2);
res=cheng(res,res);
if(n%2==1) res=cheng(res,a);
return res;
}
juzhen T_ksm(juzhen a,char s[],int len)//十进制快速幂:O(10*lg(n))
{
juzhen res=I,t=a;
for(;len>=0;len--)
{
res=cheng(res,ksm(t,s[len]-'0'));
t=ksm(t,10);
}
return res;
}
int main()
{
juzhen A,B,C;
int i,Ln,Lm;
scanf("%s%s",sn,sm);
Ln=strlen(sn)-1;
sn[Ln]--;//n--
for(i=Ln;sn[i]<'0';i--)
{
sn[i]+=10;
sn[i-1]--;
}
Lm=strlen(sm)-1;
sm[Lm]--;//m--
for(i=Lm;sm[i]<'0';i--)
{
sm[i]+=10;
sm[i-1]--;
}
scanf("%lld%lld%lld%lld",&A.v1,&A.v2,&B.v1,&B.v2);
I.v1=1;
I.v2=0;
A=T_ksm(A,sm,Lm);
C=cheng(B,A);
C=T_ksm(C,sn,Ln);
C=cheng(A,C);
printf("%lld",(C.v1+C.v2)%mod);
return 0;
}