【题解】Fibonacci前n项和

【题解】Fibonacci前n项和

题目大意

大家知道Fibonacci数列吧,f[1]=1,f[2]=1,f[3]=2,f[4]=3……也就是f[n]=f[n-1]+f[n-2]。现在问题很简单,输入n和m,求前n项和取模m。

数据范围

1<=n<=2000000000 1<=m<=1000000010

分析

数据范围很大,所以递推肯定是会爆炸的。

我们考虑用矩阵优化,(没有做过斐波那契数列?那还不快去做!)但是,这下又出现了一个问题,那就是我们如果直接用矩阵乘法的话只能求出一个数列的第n项,如何求出前n项的和......嗯,这是个问题。

但是,出题人是不可能自己坑害自己的!所以,这其中肯定是有什么规律可言。

我们发现:

\[dp[i]=dp[i-1]+dp[i-2] \]

那么,对于\(dp[n]\),我们能知道:

\[dp[n]=dp[n-1]+dp[n-2]=dp[n-2]+dp[n-3]+dp[n-3]+dp[n-4]=dp[n-2]+dp[n-3]+......=dp[1]+\sum _{i=1}^{n-2} dp[i] \]

也就是说,我们求出来的第n项,其实就是\(dp[1]到dp[n-2]\)的和再加上1。

这就好办了,我们只要求出第n+2项的值再减去1即可。

code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,m;
struct Matrix {
	ll mat[2][2];
	void clear() {
		memset(mat,0,sizeof(mat));
	}
	void idenaty() {
		clear(); 
		for(int i=0;i<2;i++) 
			mat[i][i]=1;
	} 
};
Matrix mul(Matrix a,Matrix b) {
	Matrix res;
	res.clear();
	for(int i=0;i<2;i++) {
		for(int j=0;j<2;j++) {
			for(int k=0;k<2;k++) {
				res.mat[i][j]=(res.mat[i][j]+a.mat[i][k]*b.mat[k][j]%m)%m;
			}
		}
	}
	return res;
}
Matrix power(Matrix x,ll p) {
	Matrix res;
	res.idenaty();
	while(p) {
		if(p&1) res=mul(res,x);
		x=mul(x,x);
		p>>=1;
	}
	return res;
}
Matrix a;
int main() {
	scanf("%lld%lld",&n,&m);
	a.mat[0][0]=1,a.mat[0][1]=1;
	a.mat[1][0]=1,a.mat[1][1]=0;
	Matrix res=power(a,n+1);//求出第n+2项
	printf("%lld",res.mat[0][0]-1);
	return 0;
}
/*
dp[i]= 1 * dp[i-1] + 1*dp[i-2]
dp[i-1]= 1 * dp[i-1] + 0*dp[i-2]
*/
上一篇:Java语言100例第1例——斐波那契数列


下一篇:Linux基础3(用户/组管理,rpm,yum,源码安装软件)