题目描述:就是斐波拉契数列,但是n会很大 2^48再对10e9取余,所以就不可以简单递推了
用到了矩阵相乘和矩阵快速幂
题解:斐波拉契数列 :Fn=Fn-1+Fn-2
矩阵 |Fn-1 Fn-2| 乘以一个什么样的矩阵可以变为 | Fn Fn-1| 呢?根据矩阵乘法可知为:
|1 1|
|1 0|,暂记为 a。其他题目也应该这样想,重点求这个可以用数字表示的矩阵。
|F2 F1|*a=|F3 F2|......类推可知 |Fn+1 Fn|=|F2 F1|*a^(n-1)
这样写出矩阵乘法和快速幂就可以求出 Fn。输出最后 ans.m[1][2]即可。
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
const LL MOD = 1e9;
struct Matrix
{
LL m[5][5];
int h,w;
};
Matrix Matrix_multiply(Matrix a,Matrix b) //矩阵相乘
{
Matrix c;
c.h=a.h;
c.w=b.w;
CLR(c.m,0); //初始化
for(int i=1;i<=a.h;i++)
{
for(int j=1;j<=a.w;j++)
{
if(a.m[i][j]==0)
continue;
for(int k=1;k<=b.w;k++)
c.m[i][k]=(c.m[i][k]+a.m[i][j]*b.m[j][k]%MOD)%MOD;
}
}
return c;
}
Matrix Quick(Matrix now,LL n) // now 矩阵的 n 次方,用快速幂
{
Matrix res; //保存n次后的结果,就像普通快速幂的 ans
res.h=now.h;
res.w=now.w;
CLR(res.m,0);
for(int i=1;i<=res.h;i++)
res.m[i][i]=1;
while(n)
{
if(n&1)
res=Matrix_multiply(res,now);
now=Matrix_multiply(now,now);
n>>=1;
}
return res;
}
int main()
{
int u;
scanf("%d",&u);
while(u--)
{
int k;
LL n;
scanf("%d %lld",&k,&n);
Matrix ori,pr,ans;
ori.h=ori.w=2;
CLR(ori.m,0);
ori.m[1][1]=ori.m[1][2]=ori.m[2][1]=1,ori.m[2][2]=0;
pr.h=1,pr.w=2;
CLR(pr.m,0);
pr.m[1][1]=pr.m[1][2]=1;
ans=Matrix_multiply(pr,Quick(ori,n-1));
printf("%d %lld\n",k,ans.m[1][2]);
}
return 0;
}