前提
矩阵乘法板子
struct martix{
ll m[10][10];
void init(){clean(m,0);}
};
inline martix mutiply(martix input1,martix input2,int a,int b,int c){
martix output;
output.init();
loop(i,1,a){
loop(j,1,b){
loop(k,1,c){
output.m[i][k]+=input1.m[i][j]*input2.m[j][k];
output.m[i][k]%=mod;
}
}
}
return output;
}
快速幂板子
inline martix fastpower(martix a,int times){
martix stag=a;
martix res=start_;//start_是单位矩阵,可以通过构造构造出此矩阵为对角线为1,其他都为0的矩阵
while(times){
if(times&1)res=mutiply(res,stag,2,2,2);
times>>=1;
stag=mutiply(stag,stag,2,2,2);
}
return res;
}
fibonacci 第n项
转化过程
- StepOne:写出递推式: f [ i ] = f [ i − 1 ] + f [ i − 2 ] f[i]=f[i-1]+f[i-2] f[i]=f[i−1]+f[i−2]
- StepTwo:考虑矩阵
首先, f [ i ] f[i] f[i]是由 f [ i − 1 ] , f [ i − 2 ] f[i-1],f[i-2] f[i−1],f[i−2]得出来的,所以当前矩阵应该需要 f [ i ] , f [ i − 1 ] , f [ i − 2 ] f[i],f[i-1],f[i-2] f[i],f[i−1],f[i−2]
然后根据所有的已知条件写出如下草稿:
问号那一团就是我们要构造的转移矩阵
根据等量关系:
f [ n ] = f [ n − 1 ] + f [ n − 2 ] f[n]=f[n-1]+f[n-2]\\ f[n]=f[n−1]+f[n−2]
左边那一竖列问号应该是1
根据等量关系:
f [ n − 1 ] = f [ n − 1 ] + 0 × f [ n − 2 ] f [ n − 2 ] = f [ n − 2 ] + 0 × f [ n − 1 ] f[n-1]=f[n-1]+0\times f[n-2]\\ f[n-2]=f[n-2]+0\times f[n-1] f[n−1]=f[n−1]+0×f[n−2]f[n−2]=f[n−2]+0×f[n−1]
右面一竖列问号号应该是1和0
最后构造出来的矩阵是:
设构造出的转移矩阵为s,初始答案矩阵为a,斐波那契数列的第n项为x,则
a = ( f [ 3 ] f [ 2 ] f [ 2 ] f [ 1 ] ) s = ( 1 1 1 0 ) 令 矩 阵 k = a × s n − 3 x = k 1 1 a=\begin{pmatrix} f[3] & f[2]\\ f[2] &f[1]\\ \end{pmatrix} \\s= \begin{pmatrix} 1&1\\1&0 \end{pmatrix} \\令矩阵k=a\times s^{n-3} \\x=k_{1\ 1} a=(f[3]f[2]f[2]f[1])s=(1110)令矩阵k=a×sn−3x=k1 1
- StepThree:可以搞了:
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define ll long long
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
ll n,mod;
const int maxn=2e9+10;
const int maxm=1e9+10+10;
struct martix{
ll m[10][10];
void init(){clean(m,0);}
}start_;
inline martix mutiply(martix input1,martix input2,int a,int b,int c){
martix output;
output.init();
loop(i,1,a){
loop(j,1,b){
loop(k,1,c){
output.m[i][k]+=input1.m[i][j]*input2.m[j][k];
output.m[i][k]%=mod;
}
}
}
return output;
}
inline martix fastpower(martix a,int times){
martix stag=a;
martix res=start_;
while(times){
if(times&1)res=mutiply(res,stag,2,2,2);
times>>=1;
stag=mutiply(stag,stag,2,2,2);
}
return res;
}
int main(){
#ifndef ONLINE_JUDGE
//freopen("datain.txt","r",stdin);
#endif
read(n);
read(mod);
start_.init();
start_.m[1][1]=start_.m[2][2]=1;
martix ans;
ans.init();
ans.m[1][1]=2;ans.m[1][2]=1;ans.m[2][1]=1;ans.m[2][2]=1;
if(n<=3){
if(n==3)printf("2\n");
else printf("1\n");
}
else{
martix zhuanzhi;zhuanzhi.init();
zhuanzhi.m[1][1]=1;zhuanzhi.m[1][2]=1;zhuanzhi.m[2][1]=1;zhuanzhi.m[2][2]=0;
ans=mutiply(ans,fastpower(zhuanzhi,n-3),2,2,2);
printf("%lld\n",ans.m[1][1]);
}
return 0;
}