【题解】佳佳的斐波那契数列
题目描述
求(Sigma i imes fib[i])的值
数据范围
(nle2^{31}-1)
(Solution)
看数据范围就会做的题...
[设
\
f(n):=ib[n]
\
g(n)=nf(n)
\
s(n)=Sigma^{ile n}_{i=1}g(n)
]
然后
[f(i)=f(i-1)+f(i-2)
\
s(i)=s(i-1)+g(i)
]
不好求(g),但是可以直接这样
[g(i)=i imes f(i)\
=i imes f(i-1)+i imes 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=egin{pmatrix}
\
g(i)&g(i+1)&f(i)&f(i+1)&s(i)&s(i+1)
\
\
end{pmatrix}
]
然后想办法构造一个转移矩阵
[k imes egin{pmatrix}?end{pmatrix}=egin{pmatrix}
\
g(i+1)&g(i+2)&f(i+1)&f(i+2)&s(i+1)&s(i+2)
\
\
end{pmatrix}
]
就直接根据转移式构造一下
[egin{pmatrix}?end{pmatrix}=
egin{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}
]
初始矩阵是
[egin{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
",0);
if(n==1) printf("%d
",1%mod);
if(n==2) printf("%d
",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
",ans);
return 0;
}