JZOJ-senior-4627. 【NOIP2016提高A组模拟7.15】斐波那契数列

Time Limits: 1000 ms Memory Limits: 524288 KB

Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

Sample Input

5 10

Sample Output

8
JZOJ-senior-4627. 【NOIP2016提高A组模拟7.15】斐波那契数列_第1张图片

Data Constraint

JZOJ-senior-4627. 【NOIP2016提高A组模拟7.15】斐波那契数列_第2张图片

Solution

数列的递推公式为: F [ 0 ] = 1 , F [ 1 ] = 1 , F [ n ] = F [ n − 1 ] + F [ n − 2 ] ( n > = 3 ) F[0]=1,F[1]=1,F[n]=F[n-1]+F[n-2](n>=3) F[0]=1F[1]=1F[n]=F[n1]+F[n2]n>=3
用矩阵可以这么表示:
{ F n F n − 1 } \left\{ \begin{matrix} F_n\\ F_{n-1}\\ \end{matrix} \right\} {FnFn1}

= { F n − 1 + F n − 2 F n − 1 } = \left\{ \begin{matrix} F_{n-1}+F_{n-2}\\ F_{n-1}\\ \end{matrix} \right\} ={Fn1+Fn2Fn1}

= { 1 ∗ F n − 1 + 1 ∗ F n − 2 1 ∗ F n − 1 + 0 ∗ F n − 2 } = \left\{ \begin{matrix} 1*F_{n-1}+1*F_{n-2}\\ 1*F_{n-1}+0*F_{n-2}\\ \end{matrix} \right\} ={1Fn1+1Fn21Fn1+0Fn2}

= { 11 10 } ∗ { F n − 1 F n − 2 } = \left\{ \begin{matrix} 1 1\\ 1 0\\ \end{matrix} \right\}* \left\{ \begin{matrix} F_{n-1}\\ F_{n-2}\\ \end{matrix} \right\} ={1110}{Fn1Fn2}

= { 11 10 } n − 1 ∗ { F 1 F 0 } = \left\{ \begin{matrix} 1 1\\ 1 0\\ \end{matrix} \right\}^{n-1}* \left\{ \begin{matrix} F_1\\ F_0\\ \end{matrix} \right\} ={1110}n1{F1F0}

= { 11 10 } n − 1 ∗ { 1 0 } = \left\{ \begin{matrix} 1 1\\ 1 0\\ \end{matrix} \right\}^{n-1}* \left\{ \begin{matrix} 1\\ 0\\ \end{matrix} \right\} ={1110}n1{10}

于是我们采用矩阵乘法 O ( 2 3 l o g N ) O(2^3logN) O(23logN) 顺利解决此题

Code

#include
#include
#include

#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#define ll long long

using namespace std;

const int N=2;
ll n,P;

struct matrix
{
	ll a[N][N];
}A,Ans;

matrix mul(matrix A,matrix B)
{
	matrix C;
	memset(C.a,0,sizeof(C.a));
	fo(k,0,1)
		fo(i,0,1) if(A.a[i][k])
			fo(j,0,1) if(B.a[k][j])
				C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%P)%P;
	return C;
}

matrix ksm(matrix A,ll k)
{
	matrix S;
	fo(i,0,1) fo(j,0,1) S.a[i][j]=(i==j);
	for(;k;A=mul(A,A),k>>=1)
		if(k&1) S=mul(S,A);
	return S;
}

int main()
{
	scanf("%lld%lld",&n,&P);
	A.a[0][0]=A.a[0][1]=A.a[1][0]=1,A.a[1][1]=0;
	Ans=ksm(A,n-1);
	printf("%lld",(Ans.a[0][0]+Ans.a[0][1])%P);
}

你可能感兴趣的:(矩阵乘法)