GESP C++ 4 级 · 知识点

算法:递推

GESP C++ 四级要求理解递推的思想,能从已知的初始项按规律推出后续项,并用循环或数组实现。递推题的关键只有两个:初值对不对、转移关系对不对。

对应知识域:算法:递推相关真题 4 套

本页为本站原创整理,例题与解析均由本站编写,不取自任何题库原题;考试范围以 CCF 官方公布为准,本平台不是 GESP 官方平台。

考纲要求

  • 理解递推是由已知的初始条件出发,按固定规律逐步推出后一项。
  • 能用一维数组保存中间结果,实现斐波那契数列这类数列递推。
  • 能识别递推关系中的边界条件,避免初值错误导致全部结果偏移。
  • 能判断哪些递推可以只用几个变量滚动计算,减少空间占用。

典型题型

  • 给出递推关系与初值,要求写出第 n 项。
  • 用递推解决上台阶、路径计数等问题。
  • 判断递推与递归的区别。

常见错误

  • 初值写错,后续每一项都跟着错。
  • 递推方向反了,用后一项去求前一项。
  • 数组开得太小,第 n 项越界。
  • 忘记取模或处理大数溢出。

深入理解

递推只有两个要素

递推 = 初始项 + 转移关系。初始项是已知的前几项,转移关系是用前面的项算出后面的项。斐波那契数列是最标准的例子:初始项 f[1] = 1, f[2] = 1,转移关系 f[n] = f[n-1] + f[n-2]。

long long f[100];
f[1] = f[2] = 1;
for (int i = 3; i <= n; i++) f[i] = f[i-1] + f[i-2];

写递推题先问两句:前几项是多少?第 n 项由前面哪几项决定?两句都答对,代码几乎是照抄。答错任何一句,整道题的答案都会偏。

用数组记录,避免重复计算

直接按定义写递归求斐波那契,第 40 项就要算上亿次,因为同一个 f[k] 被反复计算。递推用数组从小到大算一遍,每个值只算一次,f[40] 瞬间得到。

这就是「记忆化」的朴素形式。判断该用递推还是递归的经验是:状态只依赖前面少量几项、且从前往后推得动,就用递推。递推不会爆栈,也不会重复计算,是竞赛里更稳的写法。

初值与溢出

两个常见错误:一是初值写错,例如把 f[1] = f[2] = 1 写成只初始化 f[1],后面全变成 0;二是溢出,斐波那契到第 47 项就超过 int 的范围,必须用 long long,再大还需要高精度。

题目若只要求第 n 项而不需要历史值,可以用两个变量滚动更新,省掉数组:a = b; b = c; c = a + b;。但要注意更新的顺序,写反了会把中间值覆盖掉。

自编例题

用滚动变量求斐波那契数列

求斐波那契数列第 n 项,已知第 1 项和第 2 项都是 1,从第 3 项起每项等于前两项之和。

long long a = 1, b = 1;
for (int i = 3; i <= n; i++) {
    long long c = a + b;
    a = b; b = c;
}
cout << (n <= 2 ? 1 : b) << endl;

递推只需要前两项就能算出当前项,因此不必保存整个数列。循环里用 a 和 b 分别保存第 i 减 2 项和第 i 减 1 项,算出第 i 项后整体向前滚动。n 较小时直接输出 1,避免循环不执行时结果仍取初始值的情况。递推的时间复杂度是 O(n),空间复杂度是 O(1)。当结果增长很快时要改用 long long 或按题目要求取模。

相关真题

这块内容在整条路线里的位置:GESP C++ 4 级备考路径。

READY TO START

开始练习

先做一套本级别测评,报告会指出哪些知识点需要重点补;再回到本页对照考纲要求逐条核对,把不确定的条目记下来集中练。

常见问题

递推和递归有什么区别?

递推从初始项正向推到目标项,用循环实现;递归把问题分解成更小的同类问题,用函数调用自身实现,可能有重复计算。

递推结果太大怎么办?

按题目要求取模,或者在每一步计算后都取模。若题目不要求取模,应使用 long long 甚至高精度方法。

递推一定要用数组吗?

不一定。如果每项只依赖最近几项,用几个变量滚动即可;需要回看更早的项或输出中间结果时才用数组。

本级别其他知识点

官方依据