C++竞赛递推算法-斐波那契数列常见题型与例题详解

引入

递推≈简单的动态规划

  1. 递推是动态规划的基础:动态规划可以看作是递推的一种扩展和优化 递推通过递推公式逐步推导出问题的解 而动态规划则通过存储子问题的解来避免重复计算 从而提高效率

  2. 动态规划解决最优化问题:动态规划通常用于解决最优化问题 而递推则更多地用于解决一些简单的数学问题

  3. 状态和状态转移方程:动态规划的核心在于定义状态和状态转移方程 而递推则更多地依赖于递推公式

一、斐波拉契数列问题模型

有雌雄各一的一对兔子,2 个月后就会成熟,成熟后,每个月都会繁殖雌雄各一的一对兔子

问题:过n个月后有多少对兔子?

第四个月的兔子来源于,第三个月的兔子数量,以及第四个月新出生的兔子。

第四个月新出生的兔子的数量和两个月前的兔子数量有关,因为两个月前的兔子在这个月均已成熟,在这个月可以生下小兔子。

所以假设我们定义f[]表示第i个月的兔子数量,则能得到关系式:
fi] = f[i-1]+f[i-2]

二、斐波那契数与特殊值

斐波那契数列为1、1、2、3、5、8、13、......

特殊值:

●斐波那契数列第46项为1836311903,这是int能存储的下的斐波那契数列的项中的最大值

●斐波那契数列第92项为7540113804746346429,这是long long能存储的下的斐波那契数列的项中的最大值

三、斐波那契数列的边界、状态、递推式、目标

复制代码

1、状态:f[i]表示第i个月兔子的数量 第i个月兔子的数量=第i-1个月兔子数量+新繁殖的兔子数量 新繁殖的兔子数量=第i-2个月兔子数量

2、状态转移方程:(递推关系) f[i]=f[i-1]+f[i-2]

3、边界:(递推的起点) f[1]=1; f[2]=1;

4、目标:(递推的终点) f[n]

四、课堂练习

课堂练习1 1028 神奇的斐波那契数列

cpp 复制代码
1028   神奇的斐波那契数列
经验值:400
时间限制:1000毫秒
内存限制:128MB
题目描述 Description
斐波那契数列,又称黄金分割数列,指得是这样一个数列:数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和,即:1, 1, 2, 3, 5, 8......现给出一个正整数N,求斐波那契数列中第N项是多少?

输入描述 Input Description
输入一行,为一个正整数N(1≤N≤46)。

输出描述 Output Description
输出一行,为斐波那契数列中的第N项的数值。

样例输入 Sample Input
12
样例输出 Sample Output
144
cpp 复制代码
/*1028
斐波那契数列:
    每一项是前两项的和



递归的四要素:
状态:f[i]:就是数组元素的含义

状态转移方程:递推关系

边界:递推的起始项

目标:递推的终点



状态:f[i] 表示第i项 的数

状态转移方程:
    f[i] = f[i-1] + f[i-2]

边界:
    f[1] = 1;
    f[2] = 1;

目标:f[n]


int 范围能存下斐波那契数列第46项:1836311903
long long 范围能存下斐波那契数列第92项:7540113804746346429
*/
#include<iostream>
using namespace std;

int n, f[50];
int main(){
    cin >> n;
    f[1] = f[2] = 1; //边界
    for(int i=3; i<=n; i++){
        f[i] = f[i-1] + f[i-2];
    }
    cout << f[n];
    return 0;
}

课堂练习2 12034 疯狂的小老鼠

cpp 复制代码
12034   疯狂的小老鼠
经验值:1600
时间限制:1000毫秒
内存限制:128MB
题目描述 Description
有一对刚刚出生的小老鼠,从出生后长4个月变成成年的大老鼠,每一对成年的大老鼠每个月都生一对小老鼠,小老鼠4个月后又变成成年的大老鼠,之后每个月又生一对小老鼠。
假设第1个月初有一对已成年的大老鼠,问第d个月的老鼠数为多少对(假设老鼠不会死亡)?

输入描述 Input Description
一个整数d(1=<d<=90),表示第d个月。

输出描述 Output Description
一个整数,表示老鼠的对数。

样例输入 Sample Input
12
样例输出 Sample Output
69
cpp 复制代码
/*
f[i]: 第i个月的老鼠数量:
        上个月的老鼠数量+  4个月之前的老鼠数量

f[i]=f[i-1]+f[i-4]



边界:
    for(int i=1;i<=4;i++){
        f[i]=i+1;
    }


for(int i=1;i<=3;i++){
    f[i]=i+1;
}
*/
#include <iostream>
using namespace std;
long long f[95];
int main(){
    int d;
    cin>>d;
    //边界
    for(int i=1;i<=4;i++){
        f[i]=i+1;
    }
    //递推关系
    for(int i=5;i<=d;i++){
        f[i]=f[i-1]+f[i-4];
    }
    cout<<f[d];
    return 0;
}

课堂练习3 12032 建筑师酷丁猫

cpp 复制代码
12032   建筑师酷丁猫
经验值:1600
时间限制:1000毫秒
内存限制:128MB
题目描述 Description
我们都知道n个 3 * 1 的小矩形和一个 3 * n 的大矩形总面积是一样的。
现在酷丁猫是一个建筑师,他想用n块 3 * 1 的砖块,堆砌一面 3 * n 的墙,总共有多少种堆砌的方法?

输入描述 Input Description
一个整数n,表示3 * n的墙

输出描述 Output Description
一个整数,表示方法的数量

样例输入 Sample Input
6
样例输出 Sample Output
6
数据范围及提示 Data Size & Hint
n<=40
cpp 复制代码
#include <iostream>
using namespace std;
long long f[10005];
int n;
int main(){
    int n;
    cin>>n;
    f[1]=1;
    f[2]=1;
    f[3]=2;
    for(int i = 4;i<=n;i++){
        f[i]=f[i-1]+f[i-3];

    }
    cout<<f[n];
    return 0;
}

课堂练习4 2937 楼梯

cpp 复制代码
2937   楼梯
经验值:1200
时间限制:1000毫秒
内存限制:128MB
题目描述 Description
有 N 级的楼梯,你一开始在底部,每次可以向上迈最多 K 级楼梯(最少 1 级),问到达第 N 级楼梯有多少种不同方式。

输入描述 Input Description
两个正整数N,K

输出描述 Output Description
一个正整数,为不同方式数,由于答案可能很大,你需要输出 ans mod 100003 后的结果。

样例输入 Sample Input
5 2
样例输出 Sample Output
8
数据范围及提示 Data Size & Hint
N<=100,000,K<=100
cpp 复制代码
#include<iostream>
using namespace std;
int n,k,f[100005],sum=1;
int main(){
    cin>>n>>k;
    f[0]=1;
    for(int i=1;i<=n;i++){
        for(int j=max(0,i-k);j<=i-1;j++){
            f[i]+=f[j];
            
        }
        f[i]%=100003;
    }
    cout<<f[n]%100003;
    return 0; 
}

课堂练习5 4366搬砖(rock)

cpp 复制代码
4366   搬砖(rock)
经验值:1600
时间限制:1000毫秒
内存限制:128MB
瑶海区2019年信息学竞赛试题
 不许抄袭,一旦发现,直接清空经验!
题目描述 Description
考古队发现了一个非常巨大的古墓,具有非常高的考古价值,你随队来到了考古现场。经过紧张的发掘,古墓的墓道终于显露出来,但是它被一块块方砖封住了,现在你的任务就是帮助考古队将这些方砖移走,打通墓道。由于这些保存完好的古代方砖也是珍贵的文物,所以规定一次最多只能搬三块砖。那将这些砖头搬走共有多少种不同的搬法。
例如,现在总共有4个砖头,那么可以选择的方法有以下7种:
1,1,1,1(分4次搬完,每次搬一个砖头)
1,2,1(分3次搬完,第一次搬一个,第二次搬两个,第三次搬一个)
1,1,2(分3次搬完,第一次搬一个,第二次搬一个,第三次搬两个)
2,1,1(分3次搬完,第一次搬两个,第二次搬一个,第三次搬一个)
2,2 (分2次搬完,第一次搬两个,第二次搬两个)
1, 3 (分2次搬完,第一次搬一个,第二次搬三个)
3, 1 (分2次搬完,第一次搬三个,第二次搬一个)

输入描述 Input Description
一个1~40的正整数N,表示共有N块砖头

输出描述 Output Description
一个正整数,表示N块砖头移动的方法数

样例输入 Sample Input
4
样例输出 Sample Output
7
数据范围及提示 Data Size & Hint
1<=n<=40
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	long long n;
	cin>>n;
	long long a[95]={0,1,2,4};
	for(int i=4; i<=n; i++){
		a[i]=a[i-1]+a[i-2]+a[i-3];
	}
	cout<<a[n];
	return 0;
}

课堂练习6 2752 爬楼梯

cpp 复制代码
2752   爬楼梯
经验值:1200
时间限制:1000毫秒
内存限制:128MB
瑶海区2016年信息学竞赛试题
 不许抄袭,一旦发现,直接清空经验!
题目描述 Description
小明和同学们顺利闯过了第二关,进入第三关的时候,小明和同学们发现了一个楼梯,可是有些楼梯坏了。智慧之门门主说,只要同学们通过这个楼梯就可以游玩里面的项目,可是同学们必须为我解决一个问题,这个时候大家都迫不及待的让智慧之门门主快点说问题。智慧之门门主指着面前的楼梯说,你可以一步一级,或一步二级,也可以一步三级,但是某些台阶是坏的,即脚不能踩在上面,哪位同学能求出登上最高台阶的总方案数。小明和同学在思考?

输入描述 Input Description
第一行两个整数,第一个数为楼梯总级数n(n<50),第二个数表示有几个坏台阶m
第二行连续m个整数为坏台阶的级数。注意:数据的规模在longint范围内。

输出描述 Output Description
一个整数,表示登上最高台阶的方案数

样例输入 Sample Input
7 2
4 6
样例输出 Sample Output
6
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
long long b[55];
long long a[55]={1};
int n,t,m;
int main(){
	cin>>n>>m;
	while(m--){
		cin>>t;
		b[t]=1;
	}
	for(int i=1; i<=n; i++){
		if(b[i]==1) continue;
		for(int j=1; j<=3; j++){
            if(i-j>=0) a[i]+=a[i-j];
        }
	}
	cout<<a[n];
	return 0;
}

课堂练习7 1021 分数序列之和

cpp 复制代码
1021   分数序列之和
经验值:800
时间限制:1000毫秒
内存限制:128MB
题目描述 Description
已知一分数序列,b1/a1、b2/a2、b3/a3、b4/a4、b5/a5、......,其中b[i+1] = bi+ai,a[i+1]=bi,取b1=2,a1=1。如这个序列前6项分别是2/1,3/2,5/3,8/5,13/8,21/13。求这个分数序列的前n项之和。

输入描述 Input Description
输入有一行,包含一个正整数n(n <= 30)

输出描述 Output Description
输出有一行,包含一个浮点数,表示分数序列前n项的和,精确到小数点后5位(四舍五入)

样例输入 Sample Input
2
样例输出 Sample Output
3.50000
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int a[35]={1,1};
double ans;
int main(){
	int n;
	cin>>n;
	for(int i=2; i<=n+1; i++){
		a[i]=a[i-1]+a[i-2];
		ans+=a[i]*1.0/a[i-1];
	}
	printf("%.5f",int(ans*100000+0.5)/100000.0);
	return 0;
}
相关推荐
黄昏晓x3 小时前
C++----多态
java·jvm·c++
以己之3 小时前
NC313 两个数组的交集
算法·哈希算法
Brookty3 小时前
【算法】前缀和
java·学习·算法·前缀和·动态规划
And_Ii4 小时前
LeetCode 3397. 执行操作后不同元素的最大数量
数据结构·算法·leetcode
。TAT。4 小时前
C++ - List
数据结构·c++·学习
额呃呃4 小时前
leetCode第33题
数据结构·算法·leetcode
隐语SecretFlow4 小时前
【隐语SecretFlow用户案例】亚信科技构建统一隐私计算框架探索实践
科技·算法·安全·隐私计算·隐私求交·开源隐私计算
dragoooon344 小时前
[优选算法专题四.前缀和——NO.27 寻找数组的中心下标]
数据结构·算法·leetcode
少许极端4 小时前
算法奇妙屋(七)-字符串操作
java·开发语言·数据结构·算法·字符串操作