斐波那契数列

在我们所知道的范围内,解数列题最有效的方法是先从可能产生所求数列的无穷级数开刀。
									——葛立恒,高德纳,帕塔许尼克,《具体数学:计算机科学基础》

斐波那契数列指的是这样一个数列:1、1、2、3、5、8、13、21、……

先来一波看起来蛮难理解的定义:
在这里插入图片描述
下面是图片中的式子怎么得来的推导:

从简单的等比数列出发:

(1 + x + x2 + x3 + … + xn)(1 - x) = 1 - xn+1

等式两边同时除以 1 - x,为了不使分母为0,我们假设1 - x 不等于0

1 + x + x2 + x3 + … + xn = (1 - xn+1) / (1 - x)

这就是一个首项为1,公比为x的等比数列

接下来说说等比数列的无穷级数

x 的绝对值比 1 小时,也就是说 |x| < 1 时,如果 n 趋向于无穷大的话,那么 xn+1 趋向于 0,以下式子也就成立了:

1 + x + x2 + x3 + … + xn = 1 / (1 - x)

这样就求出了无穷级数。|x| < 1 这个条件是 n 趋向于无穷大时,xn+1 趋向于 0 的必要条件

向生成函数进军:
生成函数定义:x的幂的无限和,也就是幂级数
在这里插入图片描述
运用生成函数来求数列的通项
在这里插入图片描述
将斐波那契数列的通项 Fn 表示成 “关于 n 的有限项代数式”
在函数 F(x) 中,如果将 xn 这一项的系数用Fn 来表示,那么整个函数就可以用以下式子表示出来
在这里插入图片描述
我们知道 Fn-2 和 Fn-1 相加得到 Fn ,那么该如何让F(x)中系数为这两项的项相加呢(x的幂次方不同,不能直接相加)

x的幂次方互不相同,将不同的部分乘上x就好了。我们将 F(x) 分别和 x2 ,x1 ,x0 相乘后的式子写出来:
在这里插入图片描述
将式子A + 式子B - 式子C,式子左边变成以下形式:
在这里插入图片描述
式子右边变为以下形式:
在这里插入图片描述
已知 F0 = 0,F1 = 1,Fn-2 + Fn-1 - Fn = 0,所以得到:

F(x) · (x2 + x - 1) = -x

两边同时除以 (x2 + x - 1),整理后就能得到 F(x) 的有限项代数式:

F(x) = x / (1 - x - x2)

用无穷级数来表示
将 F(x) 有限项代数式拆成两个分式相加:
假设有4个未知常数R,S,r,s
在这里插入图片描述
计算此式子
在这里插入图片描述
即:
在这里插入图片描述
比较等式左右两边后,只要确定常数 R,S,r,s 为多少即可
在这里插入图片描述
将R和S分别转化成只含有r和s的关系式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目地址 蓝桥杯试题 历届试题 斐波那契

http://lx.lanqiao.cn/problem.page?gpid=T121

题目描述

斐波那契数列大家都非常熟悉。它的定义是:
  f(x) = 1 … (x=1,2)
  f(x) = f(x-1) + f(x-2) … (x>2)

对于给定的整数 n 和 m,我们希望求出:
  f(1) + f(2) + … + f(n)
的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式如下
  
但这个数字依然很大,所以需要再对 p 求模。

输入格式
  输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)

输出格式
  输出为1个整数,表示答案

样例输入
  2 3 5

样例输出
  0

样例输入
  15 11 29

样例输出
  25

思路

斐波那契数列:1、1、2、3、5、8、13、21、……、an

求和:Sn = a1 + a2 + a3 + … + an

Sn = 1 + a1 + a2 + a3 + … +an - 1

因为a2等于1,所以Sn = a2 + a1 + a2 + a3 + … + an - 1

即:Sn = a2 + a1 + a2 + a3 + … + an - 1

Sn = a3 + a2 + a3 + … + an - 1

Sn = a3 + a2 + a3 + … + an - 1

Sn = a4 + a3 + … + an - 1

……

Sn = an + an-1 + an - 1

即:Sn = 2an + an-1 - 1 = an+2 - 1

证毕

还有另一种证明方式 [数列的递推公式求通项]:
https://blog.csdn.net/ftx456789/article/details/82348742

本题具体公式: (an+2 - 1) % am % p


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
ll MOD;
ll quick_multi_mod(ll a, ll b)
{
	ll ans = 0;
	while (b){
		if (b & 1) ans = (ans + a) % MOD;
		a = (a + a) % MOD;
		b >>= 1;
	}
	return ans;
}

void Matrix(vector< vector<ll> > &a, vector< vector<ll> > b){
	vector< vector<ll> > temp(2, vector<ll>(2, 0));
	for (int i = 0; i < 2; i++){
		for (int j = 0; j < 2; j++){
			for (int k = 0; k < 2; k++){
				temp[i][j] = (temp[i][j] % MOD + quick_multi_mod(a[i][k], b[k][j])) % MOD;
			}
		}
	}
	for (int i = 0; i < 2; i++){
		for (int j = 0; j < 2; j++){
			a[i][j] = temp[i][j]; // 赋值
		}
	}
}

ll quick_pow_Matrix_mod(ll n)
{
	vector< vector<ll> > ans(2, vector<ll>(2, 0));
	vector< vector<ll> > temp(2, vector<ll>(2, 0));
	temp[0][1] = 1, temp[1][0] = 1, temp[1][1] = 1;
	ans[0][0] = 1, ans[1][1] = 1;
	while (n){
		if (n & 1) Matrix(ans, temp);
		Matrix(temp, temp);
		n >>= 1;
	}
	return ans[0][1];
}


ll quick_multi(ll a, ll b)
{
	ll ans = 0;
	while (b){
		if (b & 1) ans = ans + a;
		a = a + a;
		b >>= 1;
	}
	return ans;
}

void Matrix2(vector< vector<ll> > &a, vector< vector<ll> > b){
	vector< vector<ll> > temp(2, vector<ll>(2, 0));
	for (int i = 0; i < 2; i++){
		for (int j = 0; j < 2; j++){
			for (int k = 0; k < 2; k++){
				temp[i][j] = temp[i][j]+ quick_multi(a[i][k], b[k][j]);
			}
		}
	}
	for (int i = 0; i < 2; i++){
		for (int j = 0; j < 2; j++){
			a[i][j] = temp[i][j]; // 赋值
		}
	}
}

ll quick_pow_Matrix(ll n)
{
	vector< vector<ll> > ans(2, vector<ll>(2, 0));
	vector< vector<ll> > temp(2, vector<ll>(2, 0));
	temp[0][1] = 1, temp[1][0] = 1, temp[1][1] = 1;
	ans[0][0] = 1, ans[1][1] = 1;
	while (n){
		if (n & 1) Matrix2(ans, temp);
		Matrix2(temp, temp);
		n >>= 1;
	}
	return ans[0][1];
}

int main(){
	ll n, m, fib_m;
	scanf("%lld%lld%lld", &n, &m, &MOD);

	if (m > n + 2) // 如果m大于n+2,不需要计算f(m)的值
		printf("%lld\n", (quick_pow_Matrix_mod(n + 2) - 1) % MOD);
	else{ // 否则需要模上f(m)
		fib_m = quick_pow_Matrix(m); // 计算fib_m的值

		// 第m项可以不优化求出来,所以第n+2项也可以不取模优化
		printf("%lld\n", (quick_pow_Matrix(n + 2) % fib_m - 1) % fib_m % MOD);
	}
	return 0;
}

————————————————
参考大佬博客
https://blog.csdn.net/junfriends/article/details/6647086

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.DoubleBean.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值