矩阵乘法——佳佳的Fibonacci

问题 D: 【例题4】佳佳的Fibonacci

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

题目描述

佳佳对数学,尤其数列十分感兴趣,在研究Fibonacci之后,他创造出许多稀奇古怪的数列。如求S(n)表示Fibonacci数列前n项和对m取模之后的值,即S(n)=(F1+F2+...+Fn)mod m,F1=F2=1。可是这对佳佳来说还是小菜一碟。终于,他找到一个自己解决不了的数列。T(n)表示Fibonacci数列前n项变形后的和对m取模之后的值,

即T(n)=(F1+2×F2+3×F3+...+n*Fn)mod m,F1=F2=1。

输入

第一行,包含两个整数n和m。1<=n,m<=2的31次方-1

输出

共一行,T(n)的值

样例输入

5 5

样例输出

1

与前两题类似,不过这题的递推式比较难求

(1) t[n]=f[1]+2*f[2]+3*f[3]+...+n*f[n]

(2) n*s[n]=n*f[1]+n*f[2]+n*f[3]+...+n*f[n]

(2)-(1),得

(3) n*s[n]-t[n]=(n-1)*f[1]+(n-2)*f[2]+...+f[n-1]

令p[n]=n*s[n]-t[n]---------------------------------------------------->t[n]=n*s[n]-p[n]

p[n+1]=p[n]+s[n]

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

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

f[n+2]=0*p[n]+0*s[n]+1*f[n+1]+1*f[n]

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

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

\begin{pmatrix} p[n]\\ s[n]\\ f[n+1]\\ f[n] \end{pmatrix}=\begin{pmatrix} 1 & 1& 0&0 \\ 0&1 &1 &0 \\ 0& 0 & 1 &1 \\ 0& 0 & 1 & 0 \end{pmatrix}^{n-1}*\begin{pmatrix} p[1]\\ s[1]\\ f[2]\\ f[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<=4;i++)
        for(int j=1;j<=4;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<=4;i++)
        for(int j=1;j<=4;j++)
        if(x.g[i][j])
    {
        for(int k=1;k<=4;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 pn=res.g[1][1]*0+res.g[1][2]*1+res.g[1][3]*1+res.g[1][4]*1;
    if(pn>=m)pn%=m;
    long long int sn=res.g[2][1]*0+res.g[2][2]*1+res.g[2][3]*1+res.g[2][4]*1;
    if(sn>=m)sn%=m;
    long long int tn=(n*sn-pn+m)%m;
    return tn;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(f.g,0,sizeof(f.g));
    f.g[1][1]=1;
    f.g[1][2]=1;
    f.g[2][2]=1;
    f.g[2][3]=1;
    f.g[3][3]=1;
    f.g[3][4]=1;
    f.g[4][3]=1;
    long long int ans=solve();
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

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