题目:
点击打开链接
这道题可以利用矩阵快速幂做 但是有些大神硬推公式就推出来了,佩服佩服利用第一行F(1,k)推导可以发现当j为奇数(F(i,1)+F(i,2)+……+F(i,j))=F(i,j+1)-F(i,2)+F(i,1);当j为偶数的时候 (F(i,1)+F(i,2)+……+F(i,j))=F(i,j+1)-F(i,1);当n为偶数的时候我们进行(两行为一个矩阵运算){F(i,1)}={F(i-1,n+1)-F(i-1,1)}={F(i-1,n+1)}-{F(i-1,1)}F(i,2) F(i-1,n+2)-F(i-1,2) F(i-1,n+2) - F(i-1,2){F(i-1,n+1)}={0 1}{F(i-1,n)} = {0 1}^n{F(i-1,1)}F(i-1,n+2) 2 1 F(i-1,n+1 2 1 F(i-1,2){F(i,1)}=[{0 1}^n-{1 0}]{F(i-1,1)}F(i,2) 2 1 0 1 F(i-1,2){F(i,1)}=[{0 1}^n-{1 0}]^(m-1){F(1,1)}
F(i,2) 2 1 0 1 F(1,2)同理n为奇数的时候同理矩阵那个{F(i,1)}=[{0 1}^n-{-1 1}]^(m-1){F(1,1)}
F(i,2) 2 1 2 0 F(1,2)
然后直接快速幂#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
struct matrix
{
ll f[2][2];
};
matrix mul(matrix a,matrix b)
{
matrix ans;
memset(ans.f,0,sizeof(ans.f));
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
for(int k=0; k<2; k++)
{
ans.f[i][j]=(ans.f[i][j]+a.f[i][k]*b.f[k][j]%mod)%mod;
}
}
}
return ans;
}
matrix pow(matrix a, ll p)
{
matrix res;
memset(res.f,0,sizeof(res.f));
for(int i=0; i<2; i++)
res.f[i][i]=1;
while(p)
{
//cout<<"___"<<endl;
if(p&1)
res=mul(res,a);
p>>=1;
a=mul(a,a);
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
ll n,m;
while(T--)
{
scanf("%lld%lld",&n,&m);
//cout<<n<<" "<<m<<endl;
if(n%2==1)
{
matrix a;
a.f[0][0]=0;
a.f[0][1]=1;
a.f[1][0]=2;
a.f[1][1]=1;
a=pow(a,n);
a.f[0][0]+=1;
a.f[0][1]-=1;
a.f[1][0]-=2;
a=pow(a,m-1);
printf("%lld\n",(a.f[0][0]+a.f[0][1])%mod);
}
else
{
matrix a;
a.f[0][0]=0;
a.f[0][1]=1;
a.f[1][0]=2;
a.f[1][1]=1;
a=pow(a,n);
a.f[0][0]-=1;
a.f[1][1]-=1;
a=pow(a,m-1);
printf("%lld\n",(a.f[0][0]+a.f[0][1])%mod);
}
}
return 0;
}