C++矩陣加速例題斐波拉契數列變式—————TR的數列

題目描述:

TR非常喜歡數學,經常一個人拿出草稿紙研究奇奇怪怪的數學問題,最近,他突然對數列產生了興趣,他找到一個數列,類似於斐波拉契,即:Tn=1*f1+2*f2+3*f3+……+n*fn    (fn爲斐波拉契的第n項值)

現在TR想請你幫忙求Tn%m的值

輸入:

兩個用空格隔開的整數n和m

1≤n,m≤2^ {31}-1

輸出:

Tn mod m的值

輸入樣例:

5 5

輸出樣例:

1

樣例解釋:

T5 = (1*1+2*1+3*2+4*3+5*5)%5 = 46%5 = 1

思路分析:

既然提到了矩陣加速,我就不得不附上鍊接:https://blog.csdn.net/weixin_43810158/article/details/88947288

我們先來看一看狀態吧,畢竟是斐波拉契數列,那麼第i-1項和當前項是不可少的,還有答案。

哦,對了還有f[i]*i這個東西,我們就將其定義爲f1[i]。

根據一系列的推導(若無法推出,此爲大佬博客),我們可以得出所需矩陣:

\begin{bmatrix} 1& 0& 0& 0& 0\\ 0 & 0& 1 & 0 & 0\\ 1& 1 & 1 &0 &0 \\ 0& 0 &-1 & 0 &1 \\ 0 & 0 & 2&1 & 1 \end{bmatrix}

然後再思考答案矩陣,不用思考就可以明白是:

\begin{bmatrix} T_{i-2} &f1_{i-2} & f1_{i-1} &f_{i} & f_{i-1} \end{bmatrix}

最後用矩陣快速冪就可以了。

代碼實現:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
ll n1,mod;
struct node{
    ll n,m,c[10][10];
    node ()
    {
        memset(c,0,sizeof(c));
    }
    node operator*(const node &a)
    {
        node r;
        r.n=n;
        r.m=a.m;
        for(int i=1;i<=r.n;i++)
            for(int j=1;j<=r.m;j++)
                for(int k=1;k<=m;k++)
                    r.c[i][j]=(r.c[i][j]+(c[i][k]*a.c[k][j])%mod)%mod;
        return r;
    }
};
node qkpow(node a,ll p)
{
    node res;
    res.n=res.m=5;
    for(int i=1;i<=res.n;i++)
        res.c[i][i]=1;
    while(p)
    {
        if(p&1)
            res=res*a;
        a=a*a;
        p/=2;
    }
    return res;
}
int main()
{
	scanf("%lld%lld",&n1,&mod);
	node b;
	b.n=5;
	b.m=5;
	b.c[1][1]=1;
	b.c[2][3]=1;
	b.c[3][1]=1;
	b.c[3][2]=1;
	b.c[3][3]=1;
	b.c[4][3]=-1;
	b.c[4][5]=1;
	b.c[5][3]=2;
	b.c[5][4]=1;
	b.c[5][5]=1;
	node t;
	t=qkpow(b,n1-1);
	node a;
	a.n=1;
	a.m=5;
	a.c[1][1]=1;
	a.c[1][2]=1;
	a.c[1][3]=2;
	a.c[1][4]=1;
	a.c[1][5]=2;
	a=a*t;
	printf("%lld\n",a.c[1][1]%mod);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章