C++矩阵加速例题斐波拉契数列变式—————TR的数列

版权声明:蒟蒻原创博客,大佬转载也需附上链接: https://blog.csdn.net/weixin_43810158/article/details/89019536

题目描述:

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}

扫描二维码关注公众号,回复: 5911369 查看本文章

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

\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);
}

猜你喜欢

转载自blog.csdn.net/weixin_43810158/article/details/89019536