矩阵运算 + 快速幂。

快速幂算法的模板可以参考这里。
用算法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;
    
}