递推

递推

一本通 1188:菲波那契数列(2)

题目链接:信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

  • 斐波那契数列问题我们经常用递归解决,但是本题由于数据范围比较大,所以递归层数会非常多,会遇到爆栈的问题,必定会TLE
1
2
3
4
int fib(int n) {
if(n==1 || n==2) return 1;
return fib(n-1)+fib(n-2);
}
  • 因此我们选择用递推解决,同时还有一个问题,题目要求的是菲波那契数列中第$a$个数对$1000$取模得到的结果,我们只需要在计算$Fibonacci$数列的时候一边计算一边对$1000$取模就可以了,这并不会最终结果
  • 如果我们不一边计算一边取模,而是对单独我们要的那个值进行取模会遇到什么结果?在计算数列的时候就已经爆$int$、$long\ long$了,那么在累加求解的过程中就会溢出,最终得到的是负数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;

typedef long long ll;
typedef pair<int,int> PII;

// 解题思路: 想想能不能用递归做呢?不能,因为数据范围很大,递归会爆栈,一定会TLE
//int fib(int n) {
// if(n==1 || n==2)
// return 1;
// else
// return (fib(n-1)+fib(n-2))%1000;
//}

const int N=1e6+5;
int fib[N];
int n;

int main() {
cin>>n;
int temp;
// 预处理计算出所有的fib,再处理查询
// 初始化:
fib[1]=fib[2]=1;
for(int i=3;i<=N;i++) {
fib[i]=(fib[i-1]+fib[i-2])%1000;
}
while(n--) {
// scanf("%d",&temp);
// cout<<fib(temp)%1000<<endl;
// 用递推做法
scanf("%d",&temp);
cout<<fib[temp]<<endl;
}
return 0;
}

一本通 1189:Pell数列

题目链接:信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

  • 当作业咯

一本通 1190:上台阶

题目链接:信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

  • 其实这道题是动态规划中线性$DP$中非常经典的题目,非常适合新手初步接触动态规划类型题目,从动态规划的四要素来分析该问题
  1. 状态表示,$dp[i]$:到达第$i$步台阶的方案数
  2. 初始化,$dp[1]=1$,到达台阶一的方案只有一种,那就是直接走一步,$dp[2]=2$,到达台阶二的方案有两种,那就是走两个一步,或者直接走两步,$dp[3]=4$,到达台阶三的方案有四种,要么走四个一步,要么走两个两步,要么先走两步,再走两个一步,要么先走两个一步,再走一个两步
  3. 状态转移,$dp[i]=dp[i-1]+dp[i-2]+dpi-3$:到达第台阶$i$要么是从第$i-1$步台阶走一步上来的,要么是从第$i-2$步台阶走两步上来的,要么是从第$i-3$步台阶走三步上来的
  4. 目标值,要求到达第$n$步台阶方案数,所以直接输出$dp[n]$即可
  • 注意就算最大台阶只有$70$步,但数据增长速度很快,所以需要开$long \ long$才能通过
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;

typedef long long ll;
typedef pair<int,int> PII;

// 解题思路:

const int N=70+5; // 最大台阶数
ll dp[N];
int n;

int main() {
// 初始化
dp[1]=1;
dp[2]=2;
dp[3]=4;
// 预处理所有方案
for(int i=4;i<=N;i++) {
dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
}
while(cin>>n && n!=0) {
cout<<dp[n]<<endl;
}
return 0;
}
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2024 John Doe
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信