算法刷题day30:递归

目录

  • 引言
  • 一、有序分数
  • 二、正则问题
  • 三、带分数
  • 四、约数之和

引言

本篇文章主要讲了递归的一些题型,递归也是一种思想,主要是在各种题中显现这种思想,你必须要脑子里能够清楚它大概的一种路线是怎样的,或者说要抽象出来它的功能是干什么的,看成一个模块,这样写的时候才会好写,并且边界条件也会清楚一些,最主要还是要多练,加油!


一、有序分数

标签:递归

思路:这道题其实就是分别枚举分子和分母,然后找到符合条件的最简分数,最后按顺序输出即可。用两个递归或者两层 f o r for for 其实都可以,因为其实时间复杂度都差不多,都是 O ( N 2 ) O(N^2) O(N2) 。顺序输出用直接拿 s o r t sort sort 连带着 l a m b d a lambda lambda 表达式即可。

题目描述:

给定一个整数 N,请你求出所有分母小于或等于 N,大小在 [0,1] 范围内的最简分数,并按从小到大顺序依次输出。例如,当 N=5 时,所有满足条件的分数按顺序依次为:0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,1/1输入格式共一行,包含一个整数 N。输出格式
按照从小到大的顺序,输出所有满足条件的分数。每个分数占一行,格式为 a/b,其中 a 为分子, b 为分母。数据范围
1≤N≤160
输入样例:
5
输出样例:
0/1
1/5
1/4
1/3
2/5
1/2
3/5
2/3
3/4
4/5
1/1

示例代码1: dfs

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondint n;
vector<PII> res;
unordered_set<double> sset;void dfs_up(int down)
{for(int i = 0; i <= n; ++i){int up = i;double t = (double)up / down;if(t > 1) continue;if(sset.count(t)) continue;sset.insert(t);res.push_back({up,down});}
}void dfs_down(int x)
{for(int i = x; i <= n; ++i){dfs_up(i);}
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n;dfs_down(1);sort(res.begin(), res.end(), [&](PII& a, PII& b)->bool{ return ((double)a.x/a.y) < ((double)b.x/b.y); });for(auto t: res) printf("%d/%d\n", t.x, t.y);return 0;
}

示例代码2: 两层for

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondint n;
vector<PII> res;
unordered_set<double> sset;int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n;for(int i = 1; i <= n; ++i){for(int j = 0; j <= n; ++j){if(j > i) break;double t = (double)i / j;if(sset.count(t)) continue;sset.insert(t);res.push_back({j,i});}}sort(res.begin(), res.end(), [&](PII& a, PII& b){return ((double)a.x/a.y) < ((double)b.x/b.y);});for(auto t: res) printf("%d/%d\n", t.x, t.y);return 0;
}

二、正则问题

标签:递归

思路:递归和核心就是抽象出一个功能,具体就是一个函数是干什么的,然后把边界处理好就行了。这题的 d f s dfs dfs 就是计算从 k k k 开始的值。如果遇到左括号,就计算左括号之后的值,之后遇到右括号返回中间的值,如果遇到或,那就计算当前的值和之后的值取一个 m a x max max 即可。

题目描述:

考虑一种简单的正则表达式:只由 x ( ) | 组成的正则表达式。小明想求出这个正则表达式能接受的最长字符串的长度。例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。输入格式
一个由x()|组成的正则表达式。输出格式
输出所给正则表达式能接受的最长字符串的长度。数据范围
输入长度不超过100,保证合法。输入样例:
((xx|xxx)x|(x|xx))xx 
输出样例:
6

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondint k;
string str;int dfs()
{int res = 0;while(k < str.size()){char t = str[k];if(t == '('){k++;res += dfs();k++;}else if(t == '|'){k++;res = max(res,dfs());}else if(t == ')'){break;}else{res++, k++;}}return res;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> str;cout << dfs() << endl;return 0;
}

三、带分数

标签:全排列、递归

思路:其实我们可以看成从 1 ∼ 9 1\sim9 19 中选取三个数能满足以下的式子就行了,计算有多少种选法。我们可以用全排列 + + + 截取子串的方式达成目的,具体细节见代码。
n = a + b c n = a + \frac{b}{c} n=a+cb n ⋅ c = a ⋅ c + b n\cdot c = a\cdot c + b nc=ac+b

题目描述:

100  可以表示为带分数的形式:100=3+69258714还可以表示为:100=82+3546197注意特征:带分数中,数字 1∼9分别出现且只出现一次(不包含 0)。类似这样的带分数,100 有 11 种表示法。输入格式
一个正整数。输出格式
输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。数据范围
1≤N<106
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondint n;
vector<int> nums = {1,2,3,4,5,6,7,8,9};LL calc(int l, int r)
{LL res = 0;for(int i = l; i <= r; ++i) res = res * 10 + nums[i];return res;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n;LL res = 0;do{LL a = 0, b = 0, c = 0;for(int i = 0; i + 2 < 9; ++i){for(int j = i + 1; j + 1 < 9; ++j){a = calc(0,i), b = calc(i+1,j), c = calc(j+1,8);// cout << a << " " << b << " " << c << endl;if(c * n == a * c + b) res++;}// exit(0);}}while(next_permutation(nums.begin(), nums.end()));cout << res << endl;return 0;
}

四、约数之和

标签:数学、递归

思路:关于质数和约数的知识可以看我之前的博客 质数 、约数 ,我这里就不再细讲了。关于约数之和,根据公式,我们需要求出 a b a^b ab 的分解质因数的结果,由于这个数非常的大,所以直接算出结果再分解质因数是不可能的。我们可以先对 a a a 分解质因数,由算数基本定理可知: N = p 1 α 1 ⋅ p 2 α 2 ⋅ p 3 α 3 ⋅ ⋯ ⋅ p k α k , p i 为质数 N = p_{1}^{\alpha_{1}} \cdot p_{2}^{\alpha_{2}} \cdot p_{3}^{\alpha_{3}} \cdot \cdots \cdot p_{k}^{\alpha_{k}},p_{i}为质数 N=p1α1p2α2p3α3pkαk,pi为质数 N b = p 1 α 1 ⋅ b ⋅ p 2 α 2 ⋅ b ⋅ p 3 α 3 ⋅ b ⋅ ⋯ ⋅ p k α k ⋅ b , p i 为质数 N ^ b= p_{1}^{\alpha_{1}\cdot\ b} \cdot p_{2}^{\alpha_{2}\cdot\ b} \cdot p_{3}^{\alpha_{3}\cdot\ b} \cdot \cdots \cdot p_{k}^{\alpha_{k}\cdot\ b},p_{i}为质数 Nb=p1α1 bp2α2 bp3α3 bpkαk b,pi为质数 约数之和: ( p 1 0 + p 1 1 + ⋯ + p 1 α 1 ) ⋯ ( p k 0 + p k 1 + ⋯ + p k α k ) \text{约数之和:}(p_{1}^{0}+p_{1}^{1}+\cdots+p_{1}^{\alpha_{1}})\cdots(p_{k}^{0}+p_{k}^{1}+\cdots+p_{k}^{\alpha_{k}}) 约数之和:(p10+p11++p1α1)(pk0+pk1++pkαk)所以我们只需要对 a a a 分解质因数,再对该质因子的个数乘以 b b b 即可。然后就可以用公式计算了。
关于约数之和的每一项的计算,使用递归计算的,不然按照之前的办法 O ( N ) O(N) O(N) 是会超时的,而新的计算方式是 O ( l o g N ) O(logN) O(logN) 。如果k为0,那么结果为1,如果k是奇数,那么项数就是偶数,因为指数项是从0开始的,然后我们可以先算一半,然后再加上这一半后移一位的结果即 s u m ( p , k / 2 ) ⋅ ( 1 + q m i ( p , k / 2 + 1 ) ) sum(p,k/2) \cdot (1 + qmi(p,k/2+1)) sum(p,k/2)(1+qmi(p,k/2+1)) ,如果k为偶数,那么项数就是奇数,可以先减去最高位,用偶数的公式递归去算,然后再加上最高位,即 s u m ( p , k − 1 ) + q m i ( p , k ) sum(p,k-1) + qmi(p,k) sum(p,k1)+qmi(p,k) ,思路就是这样,更多细节见代码。

题目描述:

假设现在有两个自然数 A 和 B,S 是 AB 的所有约数之和。请你求出 Smod9901 的值是多少。输入格式
在一行中输入用空格隔开的两个整数 A 和 B。输出格式
输出一个整数,代表 Smod9901 的值。数据范围
0≤A,B≤5×107
输入样例:
2 3
输出样例:
15
注意: A 和 B 不会同时为 0。

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;const int N = 5e7+10, MOD = 9901;int a, b;
unordered_map<int,int> mmap;void get_diviors(int n)  // 分解质因数
{for(int i = 2; i <= n / i; ++i){if(n % i == 0){while(n % i == 0) mmap[i]++, n /= i;}}if(n > 1) mmap[n]++;
}LL qmi(LL a, LL k)
{LL res = 1;while(k){if(k & 1) res = res * a % MOD;k >>= 1;a = a * a % MOD;}return res;
}LL sum(int p, int k)
{if(k == 0) return 1;else if(k % 2) return (sum(p,k/2) * (1 + qmi(p,k/2+1)) ) % MOD;return (sum(p,k-1) + qmi(p,k)) % MOD;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> a >> b;get_diviors(a);LL res = 1;for(auto t: mmap){int p = t.first, k = t.second * b;res = res * sum(p,k) % MOD;}if(!a) res = 0;cout << res << endl;return 0;
}

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

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

相关文章

Arduino ESP8266 SSD1306 硬件I2C+LittleFS存储GBK字库实现中文显示

Arduino ESP8266 SSD1306 硬件I2C+LittleFS存储GBK字库实现中文显示 📍相关篇《Arduino esp8266 软件I2C SSD1306 +LittleFS存储GBK字库实现中文显示》 🌼显示效果: ✨将部分函数重构,和上面相关篇的软件I2C通讯相关接口函数移植过来,除了汉字显示采用自己写的API函数外…

使用 ReclaiMe Pro 恢复任意文件系统(Win/Linux/MacOS)

天津鸿萌科贸发展有限公司是 ReclaiMe Pro 数据恢复软件授权代理商。 ReclaiMe Pro 是一个通用工具包&#xff0c;几乎可以用于从所有文件系统&#xff08;从 Windows 系列文件系统、Linux 和 MacOS&#xff09;中恢复数据。此外&#xff0c;考虑到数据恢复工作的具体情况&…

如何实现Git Push之后自动部署到服务器?

在平时个人开发的过程中是不是有这样的烦恼&#xff1a; 项目开发完成&#xff0c;Push之后 登录服务器&#xff0c;手动git pull&#xff0c;然后运行部署命令 这真的很烦诶&#xff01; 那么能不能Git push之后&#xff0c;远端服务器自动 Git pull 然后运行部署命令呢&a…

2023行政区域

几乎所有业务系统&#xff0c;都会涉及行政区域。国家统计局 官网上公开了所有的区域编码&#xff0c;一年一更新。但只能在线查看&#xff0c;没有提供完整数据库下载的连接。为此&#xff0c;我编写了一个简陋的 python 脚本&#xff0c;抓取了近几年的数据&#xff0c;供大家…

ctf杂项总结

1.文件无法打开 1.1.文件拓展名损坏/错误导致 方法&#xff1a; 1.使用kali当中的file命令查看&#xff0c;之后修改为正确的后缀即可 2.通过16进制编辑器打开查看文件头 3.文件头残缺/错误&#xff0c;可以先使用kail当中的file命令查看它的类型&#xff0c;之后再通过 16…

C# EPPlus导出dataset----Excel2绘制图像

一、生成折线图方法 /// <summary> ///生成折线图 /// </summary> /// <param name="worksheet">sheet页数据 </param> /// <param name="colcount">总列数</param> /// &l…

(每日持续更新)jdk api之StreamCorruptedException基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

vue-vben-admin的编译运行

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统RuoYi-Nbcio亿事达企业管理平台 gitee源代码地址 后端代码&#xff1a;…

变量的本质和命名规则

变量的本质 内存:计算机中存储数据的地方&#xff0c;相当于一个空间变量本质:是程序在内存中申请的一块用来存放数据的小空间 变量命名规则与规范 规则: 不能用关键字 关键字:有特殊含义的字符&#xff0c;JavaScript 内置的一些英语词汇。例如:let、var、if、for等>只…

Jenkins入门指南:自动化构建与部署的艺术

概要&#xff1a; 本篇博客旨在为新手提供一个全面、易懂的Jenkins入门指南。我们将从Jenkins的基本概念讲起&#xff0c;逐步深入到安装、配置、以及如何使用Jenkins来自动化软件的构建、测试和部署过程。内容将涉及Jenkins的核心功能&#xff0c;插件管理&#xff0c;以及与…

代码随想录-动态规划7(139. 单词拆分)

139. 单词拆分 class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {vector<bool> dp(s.size()1, false);unordered_set<string> wordDict_set;for (int i0; i<wordDict.size(); i){wordDict_set.insert(wordDict[i]);}dp…

掌握AI技术,轻松学习游戏开发

进入游戏开发的世界&#xff0c;就像打开了一扇通往未来的大门&#xff0c;而掌握AI技术正是这扇门的钥匙。随着AI技术在游戏行业的迅速崛起&#xff0c;它不仅为游戏设计和用户体验带来了革命性的改变&#xff0c;更为新入行者展示了一个充满创新和机遇的领域。特别是百川智能…

HTML CSS学习

# html css 日常学习记录---学习途径--渡一教育-袁老师# 元素包含关系 以前&#xff1a;块级元素可以包含行级元素&#xff0c;行级元素不可以包含块级元素&#xff0c;a元素除外 元素的包含关系由元素的内容类别决定。 例如&#xff0c;查看h1元素中是否可以包含p元素 总…

缓存把我坑惨了..

故事 春天&#xff0c;办公室外的世界总是让人神往的&#xff0c;小猫带着耳机&#xff0c;托着腮帮&#xff0c;望着外面美好的春光神游着… 一声不和谐的座机电话声打破这份本该属于小猫的宁静&#xff0c;“hi&#xff0c;小猫&#xff0c;线上有个客户想购买A产品规格的商…

SOLIDWORKS2024 | 轻松处理制造复杂几何体和有机形状

如今&#xff0c;工程师面临各种各样的挑战。预算紧缩的同时&#xff0c;排期也越来越短。客户需要智能、互联的产品&#xff0c;这一需求掀起了各行各业添加软件和电子模块的趋势。产品须变得更快、更轻、更好。在所有这些变化中&#xff0c;几何体也变得越来越复杂。 从工作…

InstantID Zero-shot Identity-Preserving Generation in Seconds

InstantID: Zero-shot Identity-Preserving Generation in Seconds TL; DR&#xff1a;InstantID IP-Adapter (Face) ControlNet&#xff0c;实现了具有较高保真度的人脸 ID 生成。 方法 InstantID 想做到的事情是&#xff1a;给定一张参考人脸 ID 图片&#xff0c;生成该…

基于单片机的电子秤设计

摘 要 本文设计了一种以51单片机来进行控制的电子秤系统&#xff0c;系统的电路部分由以下几个电路模块组成&#xff1a;数据采集和数据处理电路、模数转换电路、LED及蜂鸣器报警电路、最小系统电路、液晶显示电路、矩阵按键电路等。接通电源后&#xff0c;单片机会把压力传感…

DeepSeek发布多模态大型语言模型DeepSeek-VL,技术创新性突出

近日,DeepSeek团队发布了一项创新性突出的多模态大型语言模型DeepSeek-VL。该模型参数规模为1.3B和6.7B,采用了创新的联合视觉和语言预训练方法,旨在解决传统的单模态预训练方法的局限性。 DeepSeek-VL在数据准备、模型架构和训练方法等多方面都有创新工作。在数据准备方面,采用…

抠图透明背景怎么做?3种方法教你抠图换背景

抠图透明背景怎么做&#xff1f;抠图透明背景是一项在图像处理中常见的任务&#xff0c;它可以帮助我们去除图片中的多余部分&#xff0c;使主体部分与背景分离&#xff0c;从而得到一个透明背景的效果。这一技巧在多个领域都有广泛应用&#xff0c;掌握这种技巧&#xff0c;不…

OMP(Orthogonal Matching Pursuit,正交匹配追踪)算法

OMP(Orthogonal Matching Pursuit,正交匹配追踪)算法,这是一种在信号处理和压缩感知领域经常使用的算法,特别适用于从稀疏信号中恢复出信息。 示例 我们可以通过一个简化的例子来理解它: 想象你有一本非常厚的书,这本书里充满了各种故事。但现在,你只能通过书中的一…