【题解】佳佳的斐波那契数列
题目描述
求\(\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;
}
原文地址:https://www.cnblogs.com/winlere/p/10805038.html