0x02递推与递归

0x02递推与递归

递推者,自小而大,循序渐进;递归者,由上而下,分而治之

文章目录

  • 0x02递推与递归
    • 例题
      • T1:
      • T2:
      • T3:
      • T4:
      • T5
      • T6

例题

T1:

92. 递归实现指数型枚举 - AcWing题库

思路:每个数分成选或者不选。边界是枚举的数不能超过n。

可以二进制枚举、也可直接递归。

#include<bits/stdc++.h>
using namespace std;
int n;vector<int> v;
void dfs(int pos){if(pos==n+1){for(int i=0;i<v.size();i++){cout<<v[i]<<' ';}cout<<endl;return;}v.push_back(pos);dfs(pos+1);v.pop_back();dfs(pos+1);
}void slove(){cin>>n;dfs(1);
}int main(){slove();
}

T2:

93. 递归实现组合型枚举 - AcWing题库

换汤不换药,修改一下边界即可。

参照上一题代码,当v.size() == m 的时候我们输出 答案

然后,为了防止枚举到超过n的数字,边界就是 n+1

#include<bits/stdc++.h>
using namespace std;int n,m;vector<int> v;void dfs(int pos){if(v.size()==m ){for(int i=0;i<v.size();i++){cout<<v[i]<<' ';}cout<<endl;return;}if(pos==n+1)return;v.push_back(pos);dfs(pos+1);v.pop_back();dfs(pos+1);}void slove(){cin>>n>>m;dfs(1);
}int main(){slove();
}

当然,上面是我写的普通方法,耗时500ms。

蓝书上面在此基础上加了一句话后,其耗时为:

if(v.size()>m or v.size()+n-pos+1<m)return;

在这里插入图片描述

这就是剪枝的思想。

我第一个程序,是只有当枚举到n+1的时候,和选了m个数的时候才会终止。

而实际上,如果当前我们选的数大于m,我们直接回溯即可,不必要继续往下再枚举,因为此后的枚举一定是无用的。

如果我们选的数很少,即时后面剩下的数全选了,也达不到m

那么我们直接返回即可,不需要再往下枚举了。

很有意思。


T3:

94. 递归实现排列型枚举 - AcWing题库

换汤换了一点点药。

这题我们在递归函数里面加一个 1~n 的循环结构,使得每次枚举都是从当前能选到的最小的数开始。

如何确定当前能选到的最小的数是多少,我们只要把已经用过的数打个标记就可以了。

所以,其实新东西也就是打标记的想法罢了。然后打完标记要恢复,这就是回溯的思想。

#include<bits/stdc++.h>
using namespace std;
const int N=100;int n;
int flag[N];vector<int> v;void dfs(int pos){if(v.size()==n){for(int i=0;i<v.size();i++)cout<<v[i]<<' ';cout<<endl;return ;}if(pos==n+1)return;for(int i=1;i<=n;i++){if(flag[i]==0){flag[i]=1;v.push_back(i);dfs(pos+1);flag[i]=0;v.pop_back();}}}void slove(){cin>>n;dfs(1);}int main(){slove();
}

T4:

95. 费解的开关 - AcWing题库

代码实现不难,但是思路难想。

有点难度的递推。

其实也就是枚举每一行的操作罢了。

用step代表我们一共操作了多少次。

首先计算如果第一行安灯那么有多少种情况。

用 1 1 1 1 1 代表每个位置的灯全被按过一次

那么总操作次数就是 ( 1<<5 )-1

枚举完第一行的操作后,我们开始枚举第二行。

第二行的操作肯定不是独立的。要在第一行的基础上进行。

如果在第一行操作完之后,第一行还有灭的灯,那么第二行对应的位置就按一次灯。

比如,第一行有两盏灯还是灭的,所以第二行只要操作两次,将第一行全部点亮即可。

此时我们第三行的操作与第二行一样。

一直递推下去,直到第五行操作完毕,此时前四行一定是全亮的,所以我们只要检查第五行有无灭的即可。

然后在此过程中,每次按灯就将step++

如果第五行全亮,我们就打擂台记录最小的step

直到枚举完所有第一行的按灯操作情况。

代码细节多,但是不难实现。

#include<bits/stdc++.h>
using namespace std;
const int N=10;char chess[N][N];int dx[]={-1,1,0,0,0},dy[]={0,0,-1,1,0};void turn(int x,int y){for(int i=0;i<5;i++){int xx=x+dx[i];int yy=y+dy[i];if(xx>=1 and xx<=5 and yy>=1 and yy<=5){chess[xx][yy]='0'+!(chess[xx][yy]-'0'); //改变状态}}}void slove(){int t;cin>>t;while(t--){for(int i=1;i<=5;i++){ //输入棋盘for(int j=1;j<=5;j++){cin>>chess[i][j];}}int ans=1000000;for(int k=0;k<(1<<5);k++){ //状压char temp[N][N];memcpy(temp,chess,sizeof chess); //备份int step=0;for(int i=0;i<5;i++) //每一位if((k>>i)&1){step++;turn(1,i+1);}for(int i=1;i<=4;i++)//递推每一行for(int j=1;j<=5;j++)if(chess[i][j]=='0'){step++;turn(i+1,j);}bool judge=1;for(int j=1;j<=5;j++){//判断是否合法if(chess[5][j]=='0'){judge=0;break;}}if(judge)ans=min(ans,step);memcpy(chess,temp,sizeof temp);}if(ans>6)ans=-1;cout<<ans<<endl;}
}int main(){slove();
}

T5

96. 奇怪的汉诺塔 - AcWing题库

思路:一道很有意思的递归,我们可以由3个柱子的汉诺塔推广到m个柱子的汉诺塔。下面给出推导过程。

设H2[i]为:在盘子只有根柱子能借助的情况下、将i个盘子全部从一根柱子移动到另一根柱子的最少移动次数。

显然,对于两个柱子的汉诺塔,i只能为1,H[1]=1

也就是说,如果盘子只能移动到一个柱子上,那么它只有一种移动方法。

设H3[i] 为:在盘子有两根柱子借助的情况下、将i个盘子全部从一根柱子移动到另一根柱子的最少移动次数。

我们可以先将j个盘子移动到b柱上,此时要移动H3[j]次

(为什么是H3[j]次?因为对于这j个盘子,它可以借助两根空柱子)

然后再将 i-j 个盘子移动到c柱子上,此时只能移动一次。

(因为下面的盘子无法借助b柱子,所以它只能去一根柱子且 i-j 必须是1。)

然后再将j个盘子移动到c柱子上。H3[j](此时这j个盘子能借助空柱子a和柱子c)

所以有递推式子:H3[i]=2*H3[j]+H2[i-j] , (i-j=1)

最终:H3[i] = 2*H3[i-1]+1

同理,如果有四根柱子:

设H4[i]为:在能借用3根柱子的情况下,i个盘子从起点去到目标柱的移动次数。

首先,先选j个盘子,从起点a去起点b暂时呆着:H4[j]

然后将起点的i-j个盘子借助 cd两根空柱子去往d : H3[i-j]

最后将 j个盘子从b移到d,而它能借助的盘子有:acd

H4[j]

所以 H4[i] = 2*H4[j] + H3[i-j]

由于 j 可以选择很多种,而我们要求的是最小移动次数,

所以我们要从 1~i-1 来枚举 j,然后取最小值即可。

那么推广到m个盘子就是:

H m [ i ] = m i n ( H m [ i ] , 2 ∗ H m [ j ] + H m − 1 [ i − j ] ) H_m[i] = min(H_m[i],2*H_m[j]+H_{m-1}[i-j]) Hm[i]=min(Hm[i],2Hm[j]+Hm1[ij])

#include<bits/stdc++.h>
#include <iostream>
#include<string>
#include<cmath>
#include <vector>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long  ll;
const int N = 1e5 + 7;int H3[20];
int H4[20];int main() {ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);// H3[i]= 把i个盘从a塔移动到c塔 = 先把j个盘从a塔移动到b塔 H[j] + 把i-j个盘从 a塔移动到c塔: 1 + 再把j个盘移动到c塔 H[j]for (int i =1; i <= 12; i++) {for (int j = 0; j <= i-1; j++) {H3[i] = 2 * H3[j] + 1;}}// H4[i] = 把i个盘从a移到d = j:a->b  H4[j] + i-j:a->d H3[i-j] + j:b->d  H4[j]memset(H4, 0x3f ,sizeof H4);H4[1] = 1;for (int i = 2; i <= 12; i++) {for (int j = 0; j <= i - 1; j++) {H4[i]= min(H4[i],2 * H4[j] + H3[i - j]);}}for (int i = 1; i <= 12; i++)cout << H4[i] << endl;
}

T6

97. 约数之和 - AcWing题库

是一道结合了 数论+分治+递归 的题目

分治部分:求等比数列+快速幂

数论部分:唯一素数分解

递归:求等比数列

大概步骤:

1、写出求递归分治求等比数列的函数

2、快速幂

3、整数分解

等比数列好求:

设 sum(p, k)= p 0 + p 1 + . . . . p k p^0+p^1+....p^k p0+p1+....pk

我们考虑将其分成长度相同的两半:

若k为奇数,那么则有偶数项:

以k=5举例推出一般式子:

s u m ( p , 5 ) = sum(p,5)= sum(p,5)= p 0 + p 1 + p 2 + p 3 + p 4 + p 5 p^0+p^1+p^2+p^3+p^4+p^5 p0+p1+p2+p3+p4+p5

= ( p 0 + p 1 + p 2 ) ( 1 + p 3 ) =(p^0+p^1+p^2)(1+p^3) =(p0+p1+p2)(1+p3)

= s u m ( p , 5 2 ) ∗ ( 1 + p 5 + 1 2 ) =sum(p,\frac{5}2)*(1+p^\frac{5+1}{2}) =sum(p,25)(1+p25+1)

一般式子: s u m ( p , k ) = s u m ( p , k 2 ) ∗ ( 1 + p k + 1 2 ) sum(p,k)=sum(p,\frac{k}2)*(1+p^\frac{k+1}{2}) sum(p,k)=sum(p,2k)(1+p2k+1)

若n为偶数,那么则有奇数项:

以k=4举例推出一般式子:

s u m ( p , 4 ) = sum(p,4)= sum(p,4)= p 0 + p 1 + p 2 + p 3 + p 4 p^0+p^1+p^2+p^3+p^4 p0+p1+p2+p3+p4

= ( p 0 + p 1 + p 2 ) ( p 2 + 1 ) − p 2 =(p^0+p^1+p^2)(p^2+1)-p^2 =(p0+p1+p2)(p2+1)p2

一般式子:

= s u m ( p , k 2 ) ∗ ( p k 2 + 1 ) − p k 2 =sum(p,\frac{k}{2})*(p^{\frac{k}{2}}+1)-p^{\frac{k}{2}} =sum(p,2k)(p2k+1)p2k

然后再写快速幂:

int qmi(int a, int k)
{a%=mod;int ans=1;while(k){if(k&1)ans=ans*a%mod;a=a*a%mod;k>>=1;}return ans;
}

所以求等比数列的函数如下:

int sum(int p, int k)
{if (k == 0) return 1;if (k % 2 == 0) return (sum(p,k/2) * (qmi(p,k/2)+1)-qmi(p,k/2)) % mod;return sum(p, k/ 2) % mod * (1+qmi(p,(k+1)/2)) % mod;
}

然后再整数分解就好了:

#include <iostream>using namespace std;const int mod = 9901;int qmi(int a, int k)
{a%=mod;int ans=1;while(k){if(k&1)ans=ans*a%mod;a=a*a%mod;k>>=1;}return ans;
}int sum(int p, int k)
{if (k == 0) return 1;if (k % 2 == 0) return (sum(p,k/2) * (qmi(p,k/2)+1)-qmi(p,k/2)) % mod;return sum(p, k/ 2) % mod * (1+qmi(p,(k+1)/2)) % mod;
}int main()
{int A, B;cin >> A >> B;int res = 1;for(int i=2;i<=A;i++){int k=0;while(A%i==0){k++;A/=i;}res=res*sum(i,k*B)%mod;}if (!A) res = 0;cout << res << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/656746.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql 插入数据

1 为表的所有字段插入数据 使用基本的INSERT语句插入数据要求指定表名称和插入到新记录中的值。基本语法格式为&#xff1a; INSERT INTO table_name (column_list) VALUES (value_list); 使用INSERT插入数据时&#xff0c;允许列名称列表column_list为空&#xff0c;此时&…

Web服务器之Tomcat

文章目录 Web 服务器软件简介资源分类访问流程常见的Web服务器软件 Tomcat简介使用步骤使用Tomcat注意事项部署项目的方式方式一方式二方式三 问题中文乱码黑窗口一闪而过启动报错 Web 服务器软件 简介 服务器&#xff1a;安装了服务器软件的计算机服务器软件&#xff1a;接收…

漏洞原理远程命令执行

漏洞原理远程命令/代码执行 远程命令执行函数&#xff08;Remote Command Execution Function&#xff09;是指在一个网络环境中&#xff0c;通过远程执行命令来控制另一个计算机系统或设备的功能。 远程命令执行函数可以通过网络协议&#xff08;如SSH、Telnet、RPC等&#x…

伊恩·斯图尔特《改变世界的17个方程》毕达哥拉斯定理笔记

它告诉我们什么&#xff1f; 直角三角形的三个边之间有什么关系。 为什么重要&#xff1f; 它提供了几何和代数之间的重要联系&#xff0c;使我们能够根据坐标计算距离。它也催生出了三角学。 它带来了什么&#xff1f; 测绘、导航&#xff0c;以及较近代出现的狭义和广义相对论…

第一节课,用户管理--后端初始化,项目调通。二次翻工2

一、网址来源&#xff1a; 快速开始 | MyBatis-Plus (baomidou.com) 进程&#xff1a; ​ 二、[此处不看]添加测试类&#xff0c;看下效果 2.1 参考 一、第一节课&#xff0c;用户管理--后端初始化&#xff0c;项目调通-CSDN博客 ​ 2.2 新建 SampleTest ​ 2.3 复…

python-自动化篇-运维-语音识别

文章目录 理论文本转换为语音使用 pyttsx使用 SAPI使用 SpeechLib 语音转换为文本 代码和效果01使用pyttsx实现文本_语音02使用SAPI实现文本_语音03使用SpeechLib实现文本_语音04使用PocketSphinx实现语音转换文本 理论 语音识别技术&#xff0c;也被称为自动语音识别&#xf…

安卓逆向学习之ADB的配置和使用及刷机root

ADB的配置和使用 ADB即Android Debug Bridge&#xff0c;安卓调试桥&#xff0c;是谷歌为安卓开发者提供的开发工具之一&#xff0c;可以让你的电脑以指令窗口的方式控制手机。可以在安卓开发者网页中的 SDK 平台工具页面下直接下载对应系统的 adb 配置文件&#xff0c;大小只…

矩阵键盘的使用

在定义局部变量时&#xff0c;一定要给该变量赋初值。在这个程序中&#xff0c;给按键按下的返回值变量 KeyNum 赋值为 20 。 矩阵键盘线行扫描法的学习链接&#xff1a;https://www.bilibili.com/video/BV1dv411z7Gd/?spm_id_from333.999.0.0&vd_sourceb91967c499b23106…

Python 因果推断(上)

引言 原文&#xff1a;causal-methods.github.io/Book/Introduction.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Vitor Kamada 电子邮件&#xff1a;econometrics.methodsgmail.com 最后更新日期&#xff1a;2020 年 8 月 15 日 这本书是使…

jupyter出现问题ModuleNotFoundError: No module named ‘exceptiongroup‘

今天使用pyg的jupyter环境发现这个环境没法用, 所以只能把这个kernel给重删了然后再装&#xff0c;操作记录如下 查看kernel jupyter kernelspec list注意不是jupyter kernel --list 需要加关键字spec, 删除kernel jupyter kernelspec remove pyg当重新安装这个kernel时可能…

Redis -- 常用数据结构,认识数据类型和编码方式

"人生就像骑自行车&#xff0c;要保持平衡&#xff0c;就必须保持前进。" — 爱因斯坦 说到数据结构&#xff0c;或许就能想到哈希表&#xff0c;列表集合等数据结构。对于redis来说对应的key的value的形式也可以是这些数据结构&#xff0c;如下&#xff1a; 针对上面…

导出Mysql数据库表名和字段并合并成一个word

参考链接&#xff1a; 导出MySQL数据库所有库和字段注释及相关信息为word文档——工具类 java - Apache POI - How to copy tables from one docx to another docx - Stack Overflow 领导让我研究下一个低代码平台的代码&#xff0c;我就想着做一个把数据库字段直接导出来的…

【论文阅读】Long-Tailed Recognition via Weight Balancing(CVPR2022)附MaxNorm的代码

目录 论文使用方法weight decayMaxNorm 如果使用原来的代码报错的可以看下面这个 论文 问题&#xff1a;真实世界中普遍存在长尾识别问题&#xff0c;朴素训练产生的模型在更高准确率方面偏向于普通类&#xff0c;导致稀有的类别准确率偏低。 key:解决LTR的关键是平衡各方面&a…

Android 12 系统开机动画

一、查找Android系统提供的开机动画 在Android系统源码目录下输入 find ./ -name "bootanimation.zip" 如图所示 所输出的路劲即为bootanimation.zip所在路径&#xff0c;每个系统都不一样&#xff0c;建议用命令查找 二、复制到对应目录下 android12\out\target\…

AIGC,ChatGPT4 实际需求效办公自动化函数应用

用实际需求来给大家演示一下ChatGPT如何助力办应用。 首先我们来提取年份值 我们将公式复制到表格即可。 接下来进行向下填充。 就得到了所有年份&#xff0c; 接下来我们完成第二个需求&#xff0c;按年份统计销售额。 Prompt&#xff1a;有一个表格C列是年份&#xff0c;D列…

【干货】【常用电子元器件介绍】【电容】(二)--电容器的主要参数、测量、选择与应用

声明&#xff1a;本人水平有限&#xff0c;博客可能存在部分错误的地方&#xff0c;请广大读者谅解并向本人反馈错误。 一、 电容器的主要参数 1.1 耐压 耐压(Voltage Rating)是指电容器在电路中长期有效地工作而不被击穿所能承受的最大直流电压。对于结构、介质、容量相同的…

【计算机网络】网络的网络

网络的网络 客户 customer 接入ISP提供商 provider 全球承载ISP多个ISP的层级结构 第一层ISP &#xff08;tier-1 ISP &#xff09; 位于顶部 区域ISP &#xff08;reginal ISP&#xff09;Level 3通信 &#xff0c;AT&T&#xff0c;Sprint &#xff0c;NTT存在点&#x…

Spring AOP实现

Spring AOP实现 AOP概述什么是AOP什么是Spring AOP Spring AOP快速入门引入依赖实现计时器 Spring AOP详解Spring AOP核心概念切点(Pointcut)连接点(Join Point)通知(Advice)切面(Aspect) 通知类型注意事项 PointCut多个切面切面优先级 Order切点表达式execution表达式annotati…

Ubuntu 隐藏Telnet主机SSH服务时显示版本信息问题

一、背景 默认情况下&#xff0c;我们通过telnet服务器的22端口&#xff0c;能够获取OpenSSH服务的banner信息(如下图所示)。而低版本的OpenSSH存在许多高危漏洞。。为了安全我们要隐藏这个信息。 二、隐藏Telnet版本信息 当使用telnet命令&#xff0c;telnet 192.168.31.20…

前缀和、差分

0x03前缀和、差分 文章目录 0x03前缀和、差分一维前缀和二维前缀和差分一维差分二维差分 习题T1T2T3 一维前缀和 数组前n项和 s [ k ] ∑ i 1 k a [ i ] s[k]\sum_{i1}^ka[i] s[k]∑i1k​a[i] s[i]s[i-1]a[i];二维前缀和 设s[i][j]表示以(1&#xff0c;1)为顶点&#xff0…