矩阵运算 + 快速幂。
快速幂算法的模板可以参考这里。
用算法4我们1秒内最多可以算到 108
级别,那当 n 更大时该怎么办呢?
可以先利用矩阵运算的性质将通项公式变成幂次形式,然后用平方倍增(快速幂)的方法求解第 n
项。
首先我们定义向量
Xn=[anan−1],边界:X1=[a1a0]
然后我们可以找出矩阵:
A=[1110]
则有:
Xn=Xn−1×A
所以:
Xn=X1×An−1
由于矩阵具有结合律,所以我们可以先求出 An−1%P
,然后再用 X1 左乘,即可求出 Xn,向量 Xn 的第一个元素就是 an
。
时间复杂度分析:快速幂的时间复杂度是 O(logn)
,所以算法5的时间复杂度也是 O(logn)。
。
根据斐波那契数项之间的关系构造矩阵。
矩阵形如{fn,fn+1,sn}。
#include<bits/stdc++.h>
using namespace std;
const int N=3;
int n,m; int a[N][N]={
{
0,1,0},{
1,1,1},{
0,0,1}},f[N]={
1,1,1}; void mul1(int a[],int b[][N],int c[])
{
int temp[N]={
0};
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
temp[i]=(temp[i]+(long long)a[j]*b[j][i])%m;
memcpy(c,temp,sizeof temp);
}
void mul2(int a[][N],int b[][N],int c[][N])//第二维大小要定义
{
int temp[N][N]={
0};
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
temp[i][j]=(temp[i][j]+(long long)a[i][k]*b[k][j])%m;
memcpy(c,temp,sizeof temp);
}
int main()
{
cin>>n>>m;
n--; while(n)
{
if(n&1)mul1(f,a,f);
mul2(a,a,a);
n>>=1;
}
cout<<f[2]<<endl;
return 0;
}