矩阵乘法——Fibonacci前n项和

问题 C: 【例题3】Fibonacci前n项和

时间限制: 1 Sec  内存限制: 128 MB
提交: 5  解决: 2
[提交][状态][讨论版][命题人:quanxing]

题目描述

大家都知道Fibonacci数列吧,f[1]=1,f[2]=1,f[3]=2,f[4]=3...也就是f[n]=f[n-1]+f[n-2]。现在,问题很简单,输入n和m,求前n项和取模m。

输入

输入n和m

1<=n<=2 000 000 000

1<=m<=1 000 000 010

输出

输出前n项和取模m。

样例输入

5 1000

样例输出

12

本题与“Fibonacci第n项”方法类似

s[n]=1*s[n-1]+1*f[n]+0*f[n-1]

f[n+1]=0*s[n-1]+1*f[n]+1*f[n-1]

f[n]=0*s[n-1]+1*f[n]+0*f[n-1]

\begin{pmatrix} s[n]\\ f[n+1]\\ f[n] \end{pmatrix}=\begin{pmatrix} 1 &1 &0 \\ 0& 1 &1 \\ 0& 1& 0 \end{pmatrix}^{n-1}*\begin{pmatrix} s[n-1]\\ f[n]\\ f[n-1] \end{pmatrix}

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
long long int n,m;
struct node
{
    long long int g[5][5];
}f,res;
void init(node &x)//构造单位矩阵
{
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        if(i==j)x.g[i][j]=1;
        else x.g[i][j]=0;
}
void multiple(node &x,node &y,node &z)//矩阵乘法运算
{
    memset(z.g,0,sizeof(z.g));
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        if(x.g[i][j])
    {
        for(int k=1;k<=3;k++)
        {
            z.g[i][k]+=x.g[i][j]*y.g[j][k];
            if(z.g[i][k]>=m)z.g[i][k]%=m;
        }
    }
}
void quickpow(int k)//快速幂
{
    init(res);
    node temp=f,t;
    while(k)
    {
        if(k&1)
        {
            multiple(res,temp,t);
            res=t;
        }
        multiple(temp,temp,t);
        temp=t;
        k>>=1;
    }
}
long long int solve()
{
    if(n<=1)return 1;
    quickpow(n-1);
    long long int ret=res.g[1][1]*1+res.g[1][2]*1+res.g[1][3]*1;
    if(ret>=m)ret%=m;
    return ret;
}
int main()
{
    scanf("%d%d",&n,&m);
    f.g[1][1]=1;
    f.g[1][2]=1;
    f.g[1][3]=0;
    f.g[2][1]=0;
    f.g[2][2]=1;
    f.g[2][3]=1;
    f.g[3][1]=0;
    f.g[3][2]=1;
    f.g[3][3]=0;
    long long int ans=solve();
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40729773/article/details/81410385