题意
已知 F1,1=F1,2=1
F1,i=F1,i−1+2F1,i−2
Fi,j=∑j+N−1k=jFi−1,k
给出N,M,求 FM,1
分析
看了官方题解才搞定的T_T,真是太菜了。
可以通过归纳法发现 Fi,j=Fi,j−1+2Fi,j−2(j≥3) (最重要的推论=-=)
拆解合并可以发现 ∑jk=1Fi,k=Fi,j+1−Fi,1 (j为偶数), ∑jk=1Fi,k=Fi,j+1−Fi,2+Fi,1 (j为奇数)。同时 Fi,k=ai,kFi,2+bi,kFi,1
再然后就是题解中写到的,
N为偶数时: (Fi,1,Fi,2)=(Fi−1,n+1−Fi−1,1,Fi−1,n+2−Fi−1,2)
=(Fi−1,n+1,Fi−1,n+2)+(−Fi−1,1,−Fi−1,2)
=(Fi−1,1,Fi−1,2)An+(Fi−1,1,Fi−1,2)B1
=(Fi−1,1,Fi−1,2)(An+B1)
(Fm,1,Fm,2)=(Fi−1,1,Fi−1,2)(An+B1)m−1
N为奇数时: (Fi,1,Fi,2)=(Fi−1,n+1−Fi−1,2+Fi−1,1,Fi−1,n+2−2Fi−1,1)
=(Fi−1,n+1,Fi−1,n+2)+(−Fi−1,2+Fi−1,1,−2Fi−1,1)
=(Fi−1,1,Fi−1,2)An+(Fi−1,1,Fi−1,2)B2
=(Fi−1,1,Fi−1,2)(An+B2)
(Fm,1,Fm,2)=(Fi−1,1,Fi−1,2)(An+B2)m−1
推出 A,B1,B2 ,套一下矩阵快速幂即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
const int mod=1e9+7;
const long long N = 3;
LL t,b,c,f1,f2;
struct Node { //矩阵
long long line,cal;
long long a[3][3];
Node(){
line=3,cal=3;
a[0][0] = 0; a[0][1] = 2; a[0][2] = 0;
a[1][0] = 0; a[1][1] = 2; a[1][2] = 1;
a[2][0] = 0; a[2][1] = 0; a[2][2] = -1;
}
friend Node operator+(Node &A,Node &B){
Node ret;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
ret.a[i][j]=((A.a[i][j]+B.a[i][j])%mod+mod)%mod;
return ret;
}
}I,B1,B2;
Node Matlab(Node x,Node s) { //矩阵乘法
Node ans;
ans.line = x.line,ans.cal = s.cal;
memset(ans.a,0,sizeof(ans.a));
for(long long i=0;i<x.line;i++) {
for(long long j=0;j<x.cal;j++) {
if(x.a[i][j]!=0)
for(long long k=0;k<s.cal;k++) {
ans.a[i][k] += x.a[i][j]*s.a[j][k];
ans.a[i][k]=((ans.a[i][k]+mod)%mod+mod)%mod;
}
}
}
return ans;
}
Node Fast_Matrax(Node tmp,LL b) { //矩阵快速幂
Node ans=I;
while(b){
if(b&1)
ans=Matlab(ans,tmp);
b>>=1;
tmp=Matlab(tmp,tmp);
}
return ans;
}
int main() {
for(int i=0;i<3;++i)
for(int j=0;j<3;++j){
if(i==j)
I.a[i][j]=1;
else
I.a[i][j]=0;
B1.a[i][j]=B2.a[i][j]=0;
}
B1.a[0][0]=-1;B1.a[0][1]=0;B1.a[0][2]=0;
B1.a[1][0]=0;B1.a[1][1]=-1;B1.a[1][2]=0;
B2.a[0][0]=1;B2.a[0][1]=-1;B2.a[0][2]=0;
B2.a[1][0]=-2;B2.a[1][1]=0;B2.a[1][2]=0;
int T;
LL n,m;
cin>>T;
while(T--){
cin>>n>>m;
Node A,tmp,tmp2;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
A.a[i][j]=0;
if(n==1 || m==1){
printf("1\n");
continue;
}
tmp=Fast_Matrax(tmp,n-1);
A.a[0][0]=((tmp.a[0][1]-tmp.a[0][2])%mod+mod)%mod;
A.a[0][1]=((tmp.a[1][1]-tmp.a[1][2])%mod+mod)%mod;
tmp=Node();
tmp=Fast_Matrax(tmp,n);
A.a[1][0]=((tmp.a[0][1]-tmp.a[0][2])%mod+mod)%mod;
A.a[1][1]=((tmp.a[1][1]-tmp.a[1][2])%mod+mod)%mod;
if(n&1)
A=A+B2;
else
A=A+B1;
A=Fast_Matrax(A,m-1);
LL ans=((A.a[0][0]+A.a[0][1])%mod+mod)%mod;
cout<<ans<<endl;
}
}