c++算法初级8——递推
c++算法初级8——递推
文章目录
- c++算法初级8——递推
- 递推
- 递推思想的运用
- 错位排序
- 杨辉三角(二维递推)
递推
递推思想:
根据已有的东西一点点地推出未知的东西。
使用递推解题三步骤:
- 数学建模
- 找出递推式和初始条件
- 写出代码。
张爽的青蛙(斐波那契)问题:地上有n个石头从左到右排成一排,张爽同学养的青蛙要从第一个石头跳到最后一个石头上,每次可以选择向右跳一格或者跳两格,问总共有多少种不同的走法?
递推表达式:设跳到第i格有 f ( i ) f(i) f(i)个跳法,则 f ( i ) = f ( i − 1 ) + f ( i − 2 ) f(i)=f(i-1)+f(i-2) f(i)=f(i−1)+f(i−2)
初始条件:f[1] = f[2] = 1。因为从1走到1只有一种方案(呆在原地不动),从1走到2也只有一种方案(走一格);
代码:
# include "bits/stdc++.h"
using namespace std;
const int MOD = 998244353; // 答案对998244353取模。
int k, f[1000010];int main()
{cin >> k;f[1] = 1;f[2] = 1;for (int i = 3; i <= k; i++){f[i] = (f[i - 1] + f[i - 2]) % MOD;}cout << f[k] << endl;return 0;
}
卡特兰数问题:由n对括号组成的括号序列,有多少种是合法的括号序列?答案对998244353取模。
什么是合法的括号序列?其定义如下:
空序列是合法的括号序列
如果A是合法的括号序列,那么(A)是合法的括号序列
如果A和B是合法的括号序列,那么AB也是合法的括号序列
简单通俗地讲,合法的括号序列就是:任何一个左括号都必须有与之对应的右括号,任何一个右括号都必须有与之对应的左括号。
比如:
()(()(()))是合法的括号序列
)(不是合法的括号序列,因为第一个右括号没有与之对应的左括号
(()))不是合法的括号序列,因为最后一个右括号没有与之对应的左括号
类似的,如果我们想用递推解决问题,我们就要找到递推式。首先开一个数组int f[n],用f[i]来表示i对括号能够组成多少种合法的括号序列。那么,怎么根据f[0], f[1], f[2], …, f[k-1]的值推出f[k]的值呢?
我们继续使用分类讨论的思想:由于合法括号序列的最后一个字符一定是右括号,不妨假设最终的括号序列长成这个样子:A(B)。其中,A和B都是合法括号序列(注意A和B可以是空序列)。
我们把最终的序列分成k种:
A由0对括号组成,B由k-1对括号组成,这样的序列有f[0] * f[k-1]种
A由1对括号组成,B由k-2对括号组成,这样的序列有f[1] * f[k-2]种
A由2对括号组成,B由k-3对括号组成,这样的序列有f[2] * f[k-3]种
……
A由m对括号组成,B由k-1-m对括号组成,这样的序列有f[m] * f[k-1-m]种
……
A由k-1对括号组成,B由0对括号组成,这样的序列有f[k-1] * f[0]种
由此,就得到了递推式
初始条件:
f(0)=1,,因为0对括号只能组成一种括号序列(空序列)
代码
# include"bits/stdc++.h"
using namespace std;
const int MOD = 998244353;
int n, f[100010];int main() {cin >> n;f[0] = 1;for (int i = 1; i <= n; i++) {for (int j = 0; j < i; j++) {f[i] = (f[i] + 1ll * f[j] * f[i - j - 1]%MOD) % MOD;}}cout << f[n] << endl;return 0;
}
时间复杂度 O ( n 2 ) O(n^2) O(n2)
递推思想的运用
错位排序
错位排列
有n个信封和n个信件,第i个信件属于第i个信封,我们想知道,有多少种不同的方法,使得没有任何一个信件被装入正确的信封中?答案对998244353取模。
下图中,2号信件装入了2号信封中,因此方案不合法
而下图,就满足“任何一个信件都没有被装入正确的信封中”,因此是合法方案:
我们开一个数组int f[n];,其中f[i]表示当信封和信件数量为i的时候,总方案数是多少。接下来,我们应该如何寻找递推式呢?
f(1)=0, f(2)=1是初始条件
考虑1号信件,它不能被装入1号信封,不妨假设它被装入了x号信封。这里为了方便,我们假设x = 3。
那么x号信件可以装入哪个信封呢?这里又存在两种情况。
第一种情况:x号信件装入了1号信封:
在这种情况下,我们可以去掉1号和x号,就变成了完全独立的子问题:n-2个信件和信封的错位排列问题。
第二种情况:x号信件没有装入1号信封。这个时候,如果我们去掉1号信件和x号信封,情况就会变成下图:
2号、4号、5号信件不能装入对应的信封中,而x号信件不能装入1号信封中,这其实也是一个大小为n-1的错位排列问题。
因此,当1号信件装入x号信封的时候,总共会有两种情况:
- x号信件装入1号信封,有f[n-2]种方案
- x号信件不装入1号信封,有f[n-1]种方案
而x的选择有n-1种(除了1都可以),因此我们得到了递推式f[n] = (n-1)(f[n-1] + f[n-2])。
代码
/*有n个信封和n个信件,第i个信件属于第i个信封,我们想知道,有多少种不同的方法,
使得没有任何一个信件被装入正确的信封中?答案对998244353取模。*/
# include<bits/stdc++.h>
using namespace std;const int mod = 998244353;
const int maxn = 100000 + 10;
//递推算法f(n) = (n-1) * (f(n-1) + f(n-2))
int main()
{int n;cin >> n;int f1 = 0, f2 = 1;int ans = 1;for(int i = 3; i <= n; i++){ans = (1LL * (i - 1) * (f1 + f2) ) % mod;f1 = f2;f2 = ans;}cout << ans << endl;
}
杨辉三角(二维递推)
事实上,我们也会经常遇到不止一维的递推,比如我们接下来要介绍的杨辉三角问题。
比如,当k=4时,你需要输出如下矩阵:
1 0 0 0 0
1 1 0 0 0
1 2 1 0 0
1 3 3 1 0
1 4 6 4 1
其中第4行第2列的数字为6(注意行和列从0开始标号),表示从4个不同的物品中选2个有6种方法。
假设这4个物品分别叫A、B、C、D,那么这6种方法分别是:
AB
AC
AD
BC
BD
CD
类似的,我们开一个二维数组int f[k][k];,其中f[i][j]表示从i个物品中选j个的方案数,接下来,我们要做的就是寻找递推式。
怎么尝试寻找递推式呢?分类讨论吗?对的!我们继续使用分类讨论来寻找递推式。绝大多数简单的递推问题都可以用分类讨论的方法找到一个合理的递推式。
假设我们现在要求的值是f[i][j],即,从i个物品中选j个的方案数,我们不妨把i个物品从1到i标上号。
现在考虑1号物品,我们尝试对1号物品进行分类讨论。怎么分类呢?无非就是两类:选1号物品,还是不选1号物品。
选1号物品:由于1号物品是一定要选进来的,因此我们还剩i-1个物品,我们要从中选出j-1个物品,方案数是f[i-1][j-1]。
不选1号物品:我们还剩i-1个物品,但是1号一定不选,因此我们还要从剩下的i-1个物品中选出j个物品,方案数是f[i-1][j]。
结束了吗?其实这样就结束了。因为我们已经不重复不遗漏地考虑到了所有可能出现的情况。
所以我们就得到了递推式:f[i][j] = f[i-1][j-1] + f[i-1][j]。
边界条件:
接下来,我们发现样例矩阵的第一列和对角线全都是1,这也是容易推理出的:第一列的所有元素都是f[x][0],从x个物品中选取0个物品,显然只有一种方案:什么都不选;而对角线的所有元素都是f[x][x],从x个物品中选出x个物品,也只有一种方案:全部都选上。
除此之外还有其他的边界条件吗?
没有了。
因为我们的递推式f[i][j] = f[i-1][j-1] + f[i-1][j]告诉我们,如果我们想要计算任何一个数字f[i][j],只需要知道它“上面”的数字f[i-1][j]和“左上方”的数字f[i-1][j-1]即可。观察矩阵,我们发现,对于任何一个数字,我们都可以用已知的初始条件推出,因此我们不需要更多的边界条件了。
除此之外还有什么需要注意的么?有的!我们还需要特别注意递推的顺序!二维递推不同于一维递推,二维的数据可能存在莫名其妙的依赖关系,因此我们在写二维递推的时候,需要特别注意二维递推的顺序。
比如杨辉三角,我们可以从递推式和上图看出,f[i]这一行的值全部由f[i-1]这一行的值推出,因此我们只需要按照行数从小到大的顺序递推即可。而其他形式的二维递推可能就需要用其他顺序进行循环,比如下面这种递推形式。
搞定了递推式、初始条件、递推顺序之后,我们的代码就呼之欲出了。
同时,递推出单个元素的复杂度是O(1),整个表格一共有O(n2)个元素,因此该算法的总时间复杂度是O(n2)。
// 杨辉三角递推
# include <bits/stdc++.h>
using namespace std;int main()
{int n;cin >> n;vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));//dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];//初始条件dp[i][0]=1,dp[i][i]=1,设置初始条件for(int i = 0; i <= n; i++){dp[i][0] = 1;dp[i][i] = 1;}//递推for(int i = 2; i <= n; i++){for(int j = 1; j <= i; j++){dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];}}//输出for(int i = 0; i <= n; i++){for(int j = 0; j <= n; j++){cout << dp[i][j] << " ";}cout << endl;}
}
相关文章:

c++算法初级8——递推
c算法初级8——递推 文章目录 c算法初级8——递推递推递推思想的运用错位排序杨辉三角(二维递推) 递推 递推思想: 根据已有的东西一点点地推出未知的东西。 使用递推解题三步骤: 数学建模找出递推式和初始条件写出代码。 张爽…...

Java后端面试题 重难点和被问到没答上来的点(包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue等)
以下是我记录的一些重点问题和面试中被问到没答上来的问题,包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue 问题目录 1.fail-safe和fail-fast2.四引用3.explain字段重要内容4.maven三大生命周期5.MYSQL 创建修改表6.数据库三范式7.Strin…...

易观千帆 | 2023年3月银行APP月活跃用户规模盘点
易观:2023年3月手机银行服务应用活跃人数53289.05万,环比增长2.15%,同比增长8.87%。 2023年3月信用卡服务应用活跃人数10800.71万,环比增长1.87%,同比增长18.64%。 2023年3月城商行手机银行服务应用活跃人数3827.43万&…...

[Android+JetPack] (Java实现) Retrofit2+RxJava3+Paging3+RecyclerView 实现加载网络数据例子 记录
文章目录 前言参考链接依赖库及版本Demo效果接口及数据展示各项模块Retrofit2Bean,对应上面的接口返回.Service API部分 Paging3PagingSource以及 RxPagingSourcePagingDataAdapter 适配器ViewModelPublicInfoPage /Activity 最后 前言 继续安卓学习之旅,本章的主要目标是: 1.完…...
Java 解析配置文件注入到配置类属性中供全局使用【开发记录】
1、背景:假设目前有两个接口,一个是查询快递订单状态的JSF接口,一个是查询快运订单状态的JSF接口,现有一个需求,要将这两个接口统一为一个入口,发布到物流开放平台供外界调用。 注意:以下代码均…...

【Python开发手册】深入剖析Google Python开发规范:规范Python注释写作
💖 作者简介:大家好,我是Zeeland,全栈领域优质创作者。📝 CSDN主页:Zeeland🔥📣 我的博客:Zeeland📚 Github主页: Undertone0809 (Zeeland) (github.com)&…...

Python入门教程+项目实战-9.3节: 字符串的操作方法
目录 9.3.1 字符串常用操作方法 9.3.2 获取字符串长度 9.3.3 字符串的大小写操作 9.3.4 删除字符串中的空白字符 9.3.5 字符串的子串查找 9.3.6 字符串的子串统计 9.3.7 字符串的子串替换 9.3.8 字符串的拆分函数 9.3.9 字符串的前缀与后缀9.3.10 知识要点 9.3.11 系…...

ENVI 5.6软件安装教程
软件下载 [软件名称]:ENVI 5.6 [软件大小]:3.25G [安装环境]:Win7~Win11或更高 软件介绍 ENVI 5.6是一款实现遥感图像处理的工具,已经广泛应用于科研、环境保护、气象、石油矿产勘探、农业、林业、医学、地球科学、公用设施管…...

在Windbg中设置断点追踪打开C++程序远程调试开关的模块
目录 1、Windbg动态调试 2、在Windbg中设置断点 2.1、在函数入口处设置断点 2.2、在函数内部某一行上设置断点 3、设置断点跟踪对打开远程调试开关接口的调用 3.1、编写演示代码 3.2、在Windbg中设置调用SetRemoteDebugOn接口的断点进行跟踪 4、最后 VC常用功能开发汇总…...

CRM客户管理软件开发功能有哪些?
互联网技术的不断提高使得企业管理方式也发生了变化,企业CRM系统应用市场逐渐扩大,相关软件开发也引起越来越多商家企业的关注。因为企业CRM系统软件开发能够根据企业需求制作,帮助企业更好的追踪管理客户信息,实时更新并进行相关…...
C++函数式魔法之旅(Journey of Functional Magic)
C函数式魔法之旅(Journey of Functional Magic) 一、引言(Introduction)C Functional模板库简介(Overview of C Functional Template Library)Functional模板库的重要性和作用(The Importance a…...

Vue基础入门(上)
<script src"https://unpkg.com/vuenext"></script> 从面向dom编程到面向数据编程 输入显示列表 const appVue.createApp({data(){return{inputValue:,list:[]}},methods:{handleAddItem(){this.list.push(this.inputValue);this.inputValue;}},templ…...
字符串匹配—KMP算法
字符串匹配的应用非常广泛,例如在搜索引擎中,我们通过键入一些关键字就可以得到相关的搜索结果,搜索引擎在这个过程中就使用字符串匹配算法,它通过在资源中匹配关键字,最后给出符合条件的搜索结果。并且我们在使用计算…...

【微信小程序】 权限接口梳理以及代码实现
1、权限接口说明 官方权限说明 部分接口需要经过用户授权统一才能调用。我们把这些接口按使用范围分成多个scope,用户选择对scope进行授权,当授权给一个scope之后,其对应的所有接口都可以直接使用。 此类接口调用时: 如…...
【每日一词】leit-motif
1、释义 leit-motif: n. 主乐调;主题;主旨。 复数:leit-motifs 2、例句 Hence the ‘ancient’ rhyme that appears as the leit-motif of The Lord of the Rings, Three Rings for the Elven-Kings under the sky, Seven for the Dwarf-lor…...
windows 环境修改 Docker 存储目录
windows 环境修改存储目录 docker 安装时不提供指定安装路径和数据存储路径的选项,且默认是安装在C盘的。C盘比较小的,等docker运行久了,一大堆的东西放在上面容易导致磁盘爆掉。所以安装前可以做些准备,让安装的实际路径不在C盘&…...
上海市青少年算法月赛丙组—目录汇总
上海市青少年算法2023年3月月赛(丙组) T1 神奇的字母序列 T2 约数的分类 T3 循环播放 T4 数对的个数 T5 选取子段 上海市青少年算法2023年2月月赛(丙组) T1 格式改写 T2 倍数统计 T3 区间的并 T4 平分数字(一…...
手动实现promise.all
手动实现promise.all function promiseAll(promises) {return new Promise((resolve, reject) > {const results [];let count 0;promises.forEach((promise, index) > {Promise.resolve(promise).then(result > {results[index] result;count;if (count promise…...

如何搭建关键字驱动自动化测试框架?这绝对是全网天花板的教程
目录 1. 关键字驱动自动化测试介绍 2. 搭建关键字驱动自动化测试框架 步骤1:选择测试工具 步骤2:定义测试用例 步骤3:编写测试驱动引擎 步骤4:实现测试关键字库 步骤5:执行测试 3. 实现关键字驱动自动化测试的关…...
字符串反转操作
1:将字符串反转 给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...