題目描述:
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]。
根據一系列的推導(若無法推出,此爲大佬博客),我們可以得出所需矩陣:
然後再思考答案矩陣,不用思考就可以明白是:
最後用矩陣快速冪就可以了。
代碼實現:
#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);
}