题意简述
给定一个二维的递推方程,已知第一项((1,1))求其第((n,m))项
分析
一道矩阵乘法基础题
一看到递推式还没有特殊条件就知道是矩阵快速幂
但是这个(n,m)的范围着实是不正常
所以考虑到要用个某某定理或者性质把(n,m)的范围缩小
这里就是费马小定理了
容易发现,这里的矩阵乘法是满足费马小定理的,但是当(a=1)的情况要特判,(至于为什么详见这篇博客或者这篇博客)
所以接下来我们可以开始构造状态矩阵
构造状态转移矩阵的方法:若状态矩阵中第 (x) 个数对下一单位时间状态矩阵中第 (y) 个数有影响,则把转移矩阵的第 (x)行第 (y) 列赋值为适当的系数。
我们发现,状态矩阵中第一个数要乘(a)加(b),那么根据上面的定义很容易想到,状态转移矩阵的第一列分别就是 (a),(b),分别对应(f_{(i-1,j)})和 (1)。我们会发现状态矩阵中第二个值是不变的,它赋值为 (1) 的意义在于能够刚好计算最后的 (+b)。
所以我们可以把单独一行的转移方程写出来:
(left{ egin{matrix} a & 0\ b & 1 end{matrix} ight})
那么其实我们每一行转移过后就是行与行之间的转移,那么我们可以把这个转移方程也直接写出来:
(left{ egin{matrix} c & 0\ d & 1 end{matrix} ight})
(其实一点变化都没有)
所以我们手摸一下,可以直接得出:
我们的初始状态的矩阵要乘上
[left[
egin{matrix}
a & 0\
b & 1
end{matrix}
ight]^{(m-1)*n}
*
left[
egin{matrix}
c & 0\
d & 1
end{matrix}
ight]^{(n-1)}
]
最后答案就是初始矩阵的元素(f_{(1,1)})
那么这道题就结束了
代码
代码附上
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
const ll MOD=1e9+7,N=1e6+5;
#define inc(a,b) (a+b>=MOD?a+b-MOD:a+b)
struct Matrix{
ll a[3][3];
Matrix(){memset(a,0,sizeof(a));}
Matrix operator * (Matrix B){
Matrix C;
for(int i=1;i<3;i++){
for(int j=1;j<3;j++){
for(int k=1;k<3;k++){
C.a[i][j]=inc(C.a[i][j],a[i][k]*B.a[k][j]%MOD);
}
}
}
return C;
}
};
Matrix QuickPow(Matrix A,ll y){
Matrix res;
res.a[1][1]=res.a[2][2]=1;
while(y){
if(y&1) res=res*A;
A=A*A;
y>>=1;
}
return res;
}
Matrix ans,base,base1;
string nn,mm;
ll a,b,c,d,n,m;
int main(){
cin>>nn>>mm>>a>>b>>c>>d;
int len1,len2;
len1=nn.size(),len2=mm.size();
for(int i=0;i<len1;i++) n=(n*10+nn[i]-'0')%(a==1?MOD:MOD-1);
for(int i=0;i<len2;i++) m=(m*10+mm[i]-'0')%(a==1?MOD:MOD-1);
ans.a[1][1]=1,ans.a[1][2]=1;
base.a[1][1]=a,base.a[2][1]=b,base.a[2][2]=1;
base=QuickPow(base,m-1);
base1.a[1][1]=c,base1.a[2][1]=d,base1.a[2][2]=1;
base=base*base1;
base=QuickPow(base,n-1);
base1.a[1][1]=a,base1.a[2][1]=b,base1.a[2][2]=1;
base1=QuickPow(base1,m-1);
write((ans*(base*base1)).a[1][1]);
return 0;
}