版权声明:蒟蒻原创博客,大佬转载也需附上链接: 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≤-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]。
根据一系列的推导(若无法推出,此为大佬博客),我们可以得出所需矩阵:
扫描二维码关注公众号,回复:
5911369 查看本文章
然后再思考答案矩阵,不用思考就可以明白是:
最后用矩阵快速幂就可以了。
代码实现:
#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);
}