Description
婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储)。她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式:
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]的值是多少,请你帮助她。由于最终结果可能很大,你只需要输出F[n][m]除以1,000,000,007的余数。
Input
一行有六个整数n,m,a,b,c,d。意义如题所述
Output
包含一个整数,表示F[n][m]除以1,000,000,007的余数
Sample Input
3 4 1 3 2 6
Sample Output
85
HINT
样例中的矩阵为:
1 4 7 10
26 29 32 35
76 79 82 85
1<=N,M<=10^1000 000,a<=a,b,c,d<=10^9
这道题给出了递推式,但是棘手的是数据范围,居然达到了变态的10^1000000,所以肯定要用一些方法加速。
加速的方法就是使用矩阵。我们先看每一行:F[i][j]=a*F[i][j-1]+b (j!=1)
,那么我们设一个初始的二阶矩阵
A
A
=表示答案,那么我们要乘的矩阵是
B
B
=。这个可以根据矩阵乘法的定义得到,因为A*B=
(a+b010)
(
a
+
b
1
0
0
)
,再*B就是
(a∗(a+b)+b010)
(
a
∗
(
a
+
b
)
+
b
1
0
0
)
。所以
A∗Bn
A
∗
B
n
后
A[0][0]=f[1][n+1]
A
[
0
]
[
0
]
=
f
[
1
]
[
n
+
1
]
。(这里矩阵从0开始)
由于F[i][1]=c*F[i-1][m]+d (i!=1)
,所以我们要将
A
A
乘,然后乘上矩阵
C
C
=,那么就会得到
f[i+1][1]
f
[
i
+
1
]
[
1
]
,而要求
f[n][m]
f
[
n
]
[
m
]
相当于就是
A∗(Bm−1∗C)n−1∗Bm−1
A
∗
(
B
m
−
1
∗
C
)
n
−
1
∗
B
m
−
1
(因为最后不用乘C),于是我么直接复杂度
O(log2N∗log2M)
O
(
l
o
g
2
N
∗
l
o
g
2
M
)
,发现n,m如此巨大,依旧过不去。所以我们要对n,m取模。具体的方法及证明我在这篇博客里写过,简单的说就是将n,m模(1000000007-1)即可。
但是还有一个问题,就是当a=1或c=1时,这个模就不适用了(费马小定理于此就不适用了),因为变成了现行的 +b + b 或 +d + d ,显然,线性加时,n、m应该模(1000000007)即可。
#include<bits/stdc++.h>
#define MD 1000000007
#define ll long long
using namespace std;
ll read(){
char c;ll x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
ll mo(string s,int mm){
ll d=0;
for(ll i=0;i<s.size();i++) d=(d*10+(s[i]-'0'))%mm;
return d;
}
string N,M;
ll n,m,a,b,c,d;
ll matr[2][2],A[2][2],B[2][2],D[2][2],I[2][2],U[2][2],C[2][2];
void mult(ll a[][2],ll b[][2]){
for(ll i=0;i<2;i++)
for(ll j=0;j<2;j++){
ll res=0;
for(ll k=0;k<2;k++) res=(res+a[i][k]*b[k][j])%MD;
U[i][j]=res;
}
for(ll i=0;i<2;i++)
for(ll j=0;j<2;j++) a[i][j]=U[i][j];
}
int main()
{
cin>>N>>M;
a=read();b=read();c=read();d=read();
if(a==1) n=mo(N,MD);else n=mo(N,MD-1);
if(c==1) m=mo(M,MD);else m=mo(M,MD-1);m--;n--;
matr[0][0]=matr[0][1]=1;matr[1][1]=matr[1][0]=0;
A[0][0]=a;A[1][0]=b;A[0][1]=0;A[1][1]=1;
B[0][0]=I[1][1]=c;B[1][0]=I[1][0]=d;B[0][1]=I[0][1]=0;B[1][1]=I[0][0]=1;I[1][0]*=-1;
D[0][0]=D[1][1]=1;D[0][1]=D[1][0]=0;
while(m){
if(m&1) mult(D,A);
mult(A,A);m>>=1;
}
C[0][0]=D[0][0];C[0][1]=D[0][1];C[1][0]=D[1][0];C[1][1]=D[1][1];mult(D,B);
while(n){
if(n&1) mult(matr,D);
mult(D,D);n>>=1;
}
mult(matr,C);
printf("%lld",matr[0][0]);
return 0;
}