简单分析,我们可以发现。如果我们能推出来某一行的第一个数字,那么直接矩乘即可。
现在怎么求呢?按照定义我们发现,首项是一个斐波那契最小展开。可以看规律:
看数字的增加数:(2/3)
3
2 3
3 2 3
2 3 3 2 3
。。。。。。。。。。。。。。。。。
值全部加起来,就是斐波那契的递推式。
所以首项的公式为: n*t+n-1 ,t = (sqrt(5)+1)/2 ,黄金分割比。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[2][2],s[2][2],n,m,mod,a1,a2;
void mul(int a[][2],int b[][2]){
int t[2][2]={0};
for(int k=0;k<2;k++)
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
t[k][i]=(t[k][i]+a[k][j]*b[j][i])%mod;
memcpy(a,t,sizeof t);
}
void qmi(int b){
while(b){
if(b&1) mul(s,a); b>>=1; mul(a,a);
}
}
signed main(){
cin>>n>>m>>mod; double t=(sqrt(5)+1)/2;
a1=(n*t+n-1); a2=2*a1-(n-1);
if(m==1) return cout<<a1%mod,0;
if(m==2) return cout<<a2%mod,0;
a[0][0]=1,a[0][1]=1,a[1][0]=1; s[0][0]=s[1][1]=1; qmi(m-2);
cout<<(a2*s[0][0]+a1*s[0][1])%mod;
return 0;
}