【题解】佳佳的斐波那契数列(矩阵)
【题解】佳佳的斐波那契数列
题目描述
求\(\Sigma i\times fib[i]\)的值
数据范围
\(n\le2^{31}-1\)
\(Solution\)
看数据范围就会做的题...
\[设
\\
f(n):=ib[n]
\\
g(n)=nf(n)
\\
s(n)=\Sigma^{i\le n}_{i=1}g(n)
\]
然后
\[f(i)=f(i-1)+f(i-2)
\\
s(i)=s(i-1)+g(i)
\]
不好求\(g\),但是可以直接这样
\[g(i)=i\times f(i)\\
=i\times f(i-1)+i\times f(i-2)
\\
=(i-1)f(i-1)+(i-2)f(i-2)+f(i-1)+2f(i-2)
\\
=g(i-1)+g(i-2)+f(i-1)+2f(i-2)
\]
于是我们构造一个行向量(矩阵)
\[k=\begin{pmatrix}
\\
g(i)&g(i+1)&f(i)&f(i+1)&s(i)&s(i+1)
\\
\\
\end{pmatrix}
\]
然后想办法构造一个转移矩阵
\[k \times \begin{pmatrix}?\end{pmatrix}=\begin{pmatrix}
\\
g(i+1)&g(i+2)&f(i+1)&f(i+2)&s(i+1)&s(i+2)
\\
\\
\end{pmatrix}
\]
就直接根据转移式构造一下
\[\begin{pmatrix}?\end{pmatrix}=
\begin{pmatrix}
0&1&0&0&0&1
\\
1&1&0&0&0&1
\\
0&2&0&1&0&2
\\
0&1&1&1&0&1
\\
0&0&0&0&0&0
\\
0&0&0&0&1&1
\end{pmatrix}
\]
初始矩阵是
\[\begin{pmatrix}
\\
1&2&1&1&1&3
\\
\\
\end{pmatrix}
\]
最后直接取出第五列就好了(\(s(i)\))
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template < class ccf >
inline ccf qr(ccf b){
register char c=getchar();register int q=1;register ccf x=0;
while(c<48||c>57)q=c==45?-1:q,c=getchar();
while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
return q==-1?-x:x;}
inline int qr(){return qr(1);}
int mod,n;
const int maxn=7;
struct MTX{
int data[maxn][maxn];
MTX(){
for(register int t=1;t<=6;++t)
for(register int i=1;i<=6;++i)
data[t][i]=0;
}
inline int* operator [](register int x){return data[x];}
inline void unis(){
for(register int t=1;t<=6;++t)
for(register int i=1;i<=6;++i)
data[t][i]=0;
for(register int t=1;t<=6;++t)
data[t][t]=1;
}
inline void operator*=(MTX& f){
MTX ret;
for(register int k=1;k<=6;++k)
for(register int t=1;t<=6;++t)
for(register int i=1;i<=6;++i)
ret[t][i]=(0ll+ret[t][i]+1ll*data[t][k]*f[k][i]%mod)%mod;
*this=ret;
}
inline void operator ^=(const int&p){
MTX base=*this,ret;ret.unis();
for(register int t=p;t;base*=base,t>>=1)
if(t&1) ret*=base;
*this=ret;
}
}yyb;
ll vec[7]={0,1,2,1,1,1,3};
int main(){
freopen("fib.in","r",stdin);
freopen("fib.out","w",stdout);
n=qr();mod=qr();
if(n<=2){
if(n< 1) printf("%d\n",0);
if(n==1) printf("%d\n",1%mod);
if(n==2) printf("%d\n",3%mod);
return 0;
}
yyb[1][1]=0;yyb[1][2]=1;yyb[1][3]=0;yyb[1][4]=0;yyb[1][5]=0;yyb[1][6]=1;
yyb[2][1]=1;yyb[2][2]=1;yyb[2][3]=0;yyb[2][4]=0;yyb[2][5]=0;yyb[2][6]=1;
yyb[3][1]=0;yyb[3][2]=2;yyb[3][3]=0;yyb[3][4]=1;yyb[3][5]=0;yyb[3][6]=2;
yyb[4][1]=0;yyb[4][2]=1;yyb[4][3]=1;yyb[4][4]=1;yyb[4][5]=0;yyb[4][6]=1;
yyb[5][1]=0;yyb[5][2]=0;yyb[5][3]=0;yyb[5][4]=0;yyb[5][5]=0;yyb[5][6]=0;
yyb[6][1]=0;yyb[6][2]=0;yyb[6][3]=0;yyb[6][4]=0;yyb[6][5]=1;yyb[6][6]=1;
yyb^=n-1;
ll ans=0;
for(register int t=1;t<=6;++t)
ans=(ans+(vec[t]*yyb[t][5])%mod)%mod;
printf("%lld\n",ans);
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!