#矩阵乘法,斐波那契#洛谷 2544 [AHOI2004] 数字迷阵

题目


分析

oeis找规律得到第一列和第二列的通项公式,然后矩阵乘法


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#define rr register
using namespace std;
const double T=0.5*(sqrt(5.0)+1);
struct maix{int p[2][2];}A,ANS;
int mod,n,m;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline maix mul(maix A,maix B){
    rr maix C; memset(C.p,0,sizeof(C.p));
    for (rr int i=0;i<2;++i)
    for (rr int j=0;j<2;++j)
    for (rr int k=0;k<2;++k)
    C.p[i][j]=mo(C.p[i][j],1ll*A.p[i][k]*B.p[k][j]%mod);
    return C;
}
signed main(){
	n=iut(); m=iut()-1; mod=iut();
	ANS.p[0][0]=(long long)(n*T+n-1)%mod;
	ANS.p[0][1]=((2*ANS.p[0][0]-n+1)%mod+mod)%mod;
	A.p[0][1]=A.p[1][0]=A.p[1][1]=1;
	if (m<2) return !printf("%d",ANS.p[0][m]);
	for (;m;m>>=1,A=mul(A,A))
	    if (m&1) ANS=mul(ANS,A);
	return !printf("%d",ANS.p[0][0]);
}
posted @ 2020-08-18 22:23  lemondinosaur  阅读(103)  评论(0编辑  收藏  举报