LOJ #10220. 「一本通 6.5 例 2」Fibonacci 第 n 项

题目描述

大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2

现在问题很简单,输入 n 和 m,求 fn mod m。

输入格式

输入 n,m。

输出格式

输出fn mod m。

样例数据

样例输入

5 1000

样例输出

5

限制与提示

对于 100% 的数据, 1≤n≤2×10^9,1≤m≤10^9+10

思路

模板题,快速幂+矩阵乘法

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

long long n,Mod;
long long a[3][3],b[3][3];
long long ans[3][3],c[3][3];

void add(long long &x,long long y) {
	x=x+y;
	x-=(x>=Mod)?Mod:0;
	return;
}

int main () {
	a[1][1]=a[1][2]=a[2][1]=1;
	a[2][2]=0;
	ans[1][1]=ans[2][2]=1;
	ans[1][2]=ans[2][1]=0;
	scanf("%lld%lld",&n,&Mod);
	n--;
	while(n) {
		if(n&1) {
			memset(c,0,sizeof(c));
			for(int i=1; i<=2; i++)
				for(int j=1; j<=2; j++)
					for(int k=1; k<=2; k++)
						add(c[i][j],ans[i][k]*a[k][j]%Mod);
			memmove(ans,c,sizeof(ans));
		}
		memset(c,0,sizeof(c));
		for(int i=1; i<=2; i++)
			for(int j=1; j<=2; j++)
				for(int k=1; k<=2; k++)
					add(c[i][j],a[i][k]*a[k][j]%Mod);
		memmove(a,c,sizeof(a));
		n>>=1;
	}
	b[1][1]=1;
	b[1][2]=0;
	memset(c,0,sizeof(c));
	for(int i=1; i<=2; i++)
		for(int j=1; j<=2; j++)
			for(int k=1; k<=2; k++)
				add(c[i][j],ans[i][k]*b[k][j]);
	memmove(b,c,sizeof(b));
	printf("%lld\n",b[1][1]);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/mysh/p/11330310.html