![](https://img-blog.csdnimg.cn/20201014180756923.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
算法笔记
无法新建文件夹
未来已来,我们就是未来
展开
-
搜索-DFS排列数字
问题https://www.acwing.com/problem/content/description/844/分析https://www.acwing.com/solution/content/30988/代码#include<iostream>using namespace std ;const int N = 10 ;int n ;// path[N] 储存路径 st[N] 存储每一点的状态int path[N], st[N] ;void dfs(int原创 2021-11-30 13:26:31 · 192 阅读 · 0 评论 -
数论-快速幂
问题https://www.acwing.com/problem/content/877/分析暴力解法直接计算 aibia_i^{b_i}aibi 然后再 mod pimod\ p_imod pi ,程序执行次数最多为:bi∗n=2e9∗1e5=2e14b_i*n=2e9*1e5=2e14bi∗n=2e9∗1e5=2e14 ,程序运行时间要求在 1.5s 内完成,明显超时快速幂整数 bbb 可以被拆成二进制表示,即 bbb 可以表示为 20 21原创 2021-11-30 12:41:42 · 196 阅读 · 0 评论 -
筛法求欧拉函数
问题https://www.acwing.com/problem/content/description/876/分析在前面求一个数所有的质数时,使用到了线性筛质数,时间复杂度 O(n)=nO(n)=nO(n)=n ,通过线性筛质数将质数筛出来的同时,计算每个数的欧拉函数。质数的欧拉函数 φ(n)=n∗(1−1n)=n−1\varphi(n)=n*(1-\frac{1}{n})=n-1φ(n)=n∗(1−n1)=n−1在线性筛质数的过程中,i%primes[j]==0i\%primes[j]==原创 2021-11-29 22:59:58 · 595 阅读 · 0 评论 -
欧拉函数实现与分析
问题https://www.acwing.com/problem/content/875/分析对于一个正整数 nnn 欧拉函数指小于或等于 nnn 的正整数中与 nnn 互质的数的数目,记作 φ(n)\varphi(n)φ(n) ,其中有 φ(1)=1\varphi(1) = 1φ(1)=1欧拉函数本身是一个积性函数,φ(m∗n)=φ(m)∗φ(n)\varphi(m*n)=\varphi(m)*\varphi(n)φ(m∗n)=φ(m)∗φ(n)已知对于每一个正整数 nnn 而言都有 n=p1α原创 2021-11-29 22:17:53 · 674 阅读 · 0 评论 -
最大公约数
问题分析一般使用辗转相除法获得最大公约数假设需要得知 a 和 b 的最大公约数 d其中有 a % b = a - k * b 其中 k = a / b ,又 d 是 a 和 b 的最大公约数,所以 d 又是 a - k * b 的公约数,即又是 a % b 的最大公约数,通过不断的 a % b 直到 b = 0 ,此时剩下的整数 a 即最大公约数代码#include<iostream>using namespace std ;int gcd(int a, int b){原创 2021-11-29 21:19:33 · 500 阅读 · 0 评论 -
所有约数之和
问题https://www.acwing.com/problem/content/873/分析已知最后乘积得到的数为N=P1α1∗P2α2∗...∗PkαkN = P^{\alpha_{1}}_{1} * P^{\alpha_{2}}_{2} *...* P^{\alpha_{k}}_{k}N=P1α1∗P2α2∗...∗Pkαk每一个约数都可以表示为p1β1∗p2β2∗...∗pkβkp^{\beta_{1}}_{1} * p^{\beta_{2}}_{2} * ... *原创 2021-11-29 13:09:13 · 66 阅读 · 0 评论 -
约数的个数
问题https://www.acwing.com/problem/content/872/分析约数的个数相比于质数的个数非常大,100 个最大值为 2e9 的数相乘,约数的个数计算。每一个数可以分解为:N=P1α1∗P2α2∗...∗PkαkN = P^{\alpha_{1}}_{1} * P^{\alpha_{2}}_{2} *...* P^{\alpha_{k}}_{k}N=P1α1∗P2α2∗...∗Pkαk因为每一个约数都可以表示为p1β1∗p2β2∗...∗pkβk原创 2021-11-29 12:30:55 · 52 阅读 · 0 评论 -
试除法求约数
问题https://www.acwing.com/problem/content/871/分析约数指可以整除被除数的数,通过 n % i == 0 判断结束后加到 vector 数组中即可。对于频繁向队尾加入数据的使用 vector 中的 push_back() 会相当方便代码#include<iostream>#include<algorithm>#include<vector>using namespace std ;vector<int&原创 2021-11-29 09:45:11 · 320 阅读 · 0 评论 -
线性筛质数
问题https://www.acwing.com/problem/content/870/分析每一个数判断是否为质数都需要从 2 遍历到 自己,对于每一个数的时间复杂度是 n2,总的时间复杂度是 1 + 22 + 32 + … + n2,最后得到的数量级为 n3,本体的数据最大为 1e6,会TLE,需要使用线性筛质数的方式来进行筛分,时间复杂度基本为 O(n)线性筛质数的主要思路是通过最小质因子筛合数线性筛质数保证每次 i * primes[j] 的最小质因子都是 primes[j],如果 i原创 2021-11-29 09:27:15 · 84 阅读 · 0 评论 -
线性筛质数
问题https://www.acwing.com/problem/content/870/分析每一个数判断是否为质数都需要从 2 遍历到 自己,对于每一个数的时间复杂度是 n2,总的时间复杂度是 1 + 22 + 32 + … + n2,最后得到的数量级为 n3,本体的数据最大为 1e6,会TLE,需要使用线性筛质数的方式来进行筛分,时间复杂度基本为 O(n)线性筛质数的主要思路是通过最小质因子筛合数代码#include<iostream>using namespace std原创 2021-11-28 21:38:04 · 134 阅读 · 0 评论 -
分解质因数
问题https://www.acwing.com/problem/content/869/分析质因数的定义质因数在数论中表示能整除给定正整数的质数,正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以用指数表示。根据算数基本定理,任何正整数皆有独一无二的质因子分解式。只有一个质因子的正整数为质数。分析按照定义写代码就好了,存储下来每个质因数和对应的指数。代码#include<iostream>using namespace std ;void divide原创 2021-11-28 20:48:34 · 327 阅读 · 0 评论 -
试除法判定质数
题目https://www.acwing.com/problem/content/868/分析质数的定义只有两个正因数 (1、自己) 的自然数为质数,比 1 大但是不是素数的数称为合数。1 和 0 既非素数也非合数思路对于一个数 a ,从 2 开始遍历到 i * i <= a ,如果能整除意味着不是素数,如果不能意味着是素数。为什么是 i * i <= a 呢,因为如果 i 是 a 的除数,则 a / i 也是 a 的除数,在代码编写的过程中,需要使用 i <= a / i原创 2021-11-28 20:21:41 · 220 阅读 · 0 评论 -
DP-整数划分
问题:https://www.acwing.com/activity/content/problem/content/1008/分析:状态表示:首先是状态表示,题目中要求得到的是 n 的所有可能的组成方案数量。初定状态量为二维 f[i, j] 表示用前 i 个数据组成 j 的可能方案数。状态划分:将问题看作完全背包类问题进行划分,f[i, j] 可以被第 i 个元素选多少个进行划分。不选第 i 个元素的方案数为前 i - 1 个数组成 j 的方案数:f[i - 1, j]选第 i 个元素的原创 2021-11-28 18:37:54 · 60 阅读 · 0 评论 -
DP-石子合并
问题:https://www.acwing.com/activity/content/problem/content/1007/分析:该题的石子合并有明显的阶段性,不能使用贪心来做,只能使用区间DP定义状态 f[i, j] 为合并 i 到 j 的所有石子的代价和,可以将状态划分为 f[i, k] + f[k + 1, j] + s[j] - s[i - 1] k ∈ [i, j - 1] 通过分组将 f[i, j] 的所有可能划分出来,其中 s[j] 表示 j 的前缀和区间DP的问题,总是通过选定原创 2021-11-28 14:41:14 · 51 阅读 · 0 评论 -
DP-石子合并
问题:https://www.acwing.com/activity/content/problem/content/1007/分析:该题的石子合并有明显的阶段性,不能使用贪心来做,只能使用区间DP定义状态 f[i, j] 为合并 i 到 j 的所有石子的代价和,可以将状态划分为 f[i, k] + f[k + 1, j] + s[j] - s[i - 1] k ∈ [i, j - 1] 通过分组将 f[i, j] 的所有可能划分出来,其中 s[j] 表示 j 的前缀和区间DP的问题,总是通过选定原创 2021-11-28 14:23:32 · 42 阅读 · 0 评论 -
DP-编辑距离
问题:https://www.acwing.com/activity/content/problem/content/1006/分析:主体思路与最短编辑距离类似,只是需要进行 n2 个判断,将最短编辑距离用函数实现,不停的调用即可。代码:#include<iostream>#include<cstring>using namespace std ;const int N = 15, M = 1010 ;int n, m ;char a[M][N] ;int原创 2021-11-28 11:11:24 · 43 阅读 · 0 评论 -
DP-最短编辑距离
问题:https://www.acwing.com/activity/content/problem/content/1094/分析:状态表示:每一点的状态 f[i, j] 表示改点进行过的增删改的最小操作次数。状态划分:状态划分即为增删改。增:意味着增加了 b[j] 后 a[1 ~ i] + b[j] = b[1 ~ j] 即 a[1 ~ i] = b[1 ~ j - 1] 此时的状态变化为 f[i, j] = f[i, j - 1] + 1删:意味着删除了 a[i] 后 a[1 ~ i原创 2021-11-28 10:17:57 · 51 阅读 · 0 评论 -
DP-最长公共子序列
问题:https://www.acwing.com/activity/content/problem/content/1005/分析:状态表示:最长公共子序列,首先进行状态表示 f[i, j] 表示第一个字符串前 i 个字符中与第二个字符串前 j 个字符中的最长公共子序列。状态划分:以最长公共子序列中的最后一个元素是否为 a[i], b[j] 来进行划分如果最后一个元素既不是 a[i] 也不是 b[j] 相当于 a[i] != b[j] 此时的 f[i, j] = f[i - 1, j - 1原创 2021-11-28 09:33:56 · 76 阅读 · 0 评论 -
DP优化-最长上升子序列
问题:https://www.acwing.com/activity/content/problem/content/1004/思路:朴素做法中的每一个状态的最大值都是由前面所有状态的最大值得到的。时间复杂度是状态的数量和状态的计算量的乘积,为 n2 。在本题中会超时,所以需要对状态数的计算进行优化。使用一个数组储存 f[i] 状态时已经存在的最长子序列。比如:1 3 4 6 5 2 ,a[4] 的数值为 5,已经存在的最长子序列为 1 3 4 6 . 通过查找该子序列中第一个大于等于 5 的值可以原创 2021-11-26 23:07:24 · 147 阅读 · 0 评论 -
DP-最长上升子序列
问题:https://www.acwing.com/activity/content/problem/content/1003/分析:需要找到最长的上升子序列,可以定义序列中每一个数的状态为 f[i] 表示以 a[i] 结尾的上升子序列中最长的一个,状态可以划分为在 a[j] < a[i] 里寻找 f[j] 的最大值,加 1 后赋值给 f[i] 。代码:#include<iostream>#include<algorithm>using namespace st原创 2021-11-26 21:16:38 · 125 阅读 · 0 评论 -
DP-数字三角形
问题:https://www.acwing.com/activity/content/problem/content/1002/分析:对数字三角形建立坐标系,每一行看作 i ,从斜45°向上的每条线看作 j ,从上往下以0开始。假设每一点的状态为f[i, j]则这一点的状态可以划分为f[i - 1, j] + a[i, j],和f[i - 1, j - 1] + a[i, j]。同时需要注意需要多拓展一层方便进行计算,同时初始化值为负无穷。赋值时可以使用 memest 进行赋值,其中 0x7f 是原创 2021-11-25 23:28:00 · 199 阅读 · 0 评论 -
DP-分组背包
题目:https://www.acwing.com/activity/content/problem/content/1001/分析:分组背包的状态划分 f[i, j] 为在背包容量为 j 的前提下,第 i 个物品组中的不选或者选哪个的问题,选择满足条件下的最大值。代码:#include<iostream>using namespace std ;const int N = 110 ;int n, m ;int v[N][N], w[N][N], s[N] ;int f原创 2021-11-24 22:57:58 · 47 阅读 · 0 评论 -
DP-多重背包2
问题:https://www.acwing.com/activity/content/problem/content/1000/分析:题目中的数据量为1000,2000,2000,如果使用朴素做法,时间复杂度是40亿。会导致TLE可以使用2进制将每一个物品的数量存储到背包里面,变成 0-1 背包问题,其中背包中物品的数量会变为 log2(2000) < 3log2(10) < 12,时间复杂度会变为 12 × 1000 × 2000 = 2.4e6 ,c ++ 可以在1秒内算完,不会TL原创 2021-11-24 21:58:55 · 158 阅读 · 0 评论 -
DP-多重背包
问题:https://www.acwing.com/activity/content/problem/content/999/分析:多重背包相当于对完全背包限制了数量,对0-1背包增加了数量。讨论方法和多重背包的朴素做法一致,因为分项时发现不能使用f[i, j - v[i]] 来化简,所以只存在一个朴素做法。暴力做法可以将每一个物品按照选择的数量从0 -> s[i] 展开转变为01背包来做。朴素代码:#include<iostream>using namespace std原创 2021-11-23 22:13:24 · 91 阅读 · 0 评论 -
DP-完全背包
问题:https://www.acwing.com/activity/content/problem/content/998/朴素解法:完全背包的物品数量没有限制,状态表示 f[i, j] 为第 i 个物品在体积为 j 时最大价值状态划分每个 i 的数量不限,则可以选择 k 个,k = 1 … j / v[i] 。遍历所有 k 的取值取最大。状态转移f[i, j] = max(f[i, j], f[i - 1, j - k * v[i]] + k * w[i])朴素解法代码实现#inclu原创 2021-11-23 21:05:57 · 157 阅读 · 0 评论 -
DP-01背包
问题:https://www.acwing.com/activity/content/problem/content/997/思路:DP问题主要是状态转移和状态划分,01背包问题实质上就是判断每一个物品取或者不取。一共N个物品,则总共判断N次。状态表示每个状态表示为 f[i, j] 意为在 j 的体积下,前 i 个物品的价值和的最大值。其中 f[0, 0] = 0,表示体积为 0 ,不存放物品。对状态进行划分:当 j < v[i] 时,表示当前 j 这个体积下,无法存放 i 这个物品,原创 2021-11-23 20:05:31 · 199 阅读 · 0 评论 -
贪心问题-区间分组
题目:https://www.acwing.com/activity/content/problem/content/1113/分析:属于求解最大区间厚度的问题,每一个区间组合里面都没有重合,将所有区间的左端点和右端点储存起来进行排序,遇到左端点区间厚度+1,遇到右端点区间厚度-1,最大值就是最大的区间厚度。代码:数据范围数据范围都在 int 数据范围内,使用 int 存储代码思路需要对所有左端点和右端点进行排序,还要能够对左端点右端点进行区分。可以将所有左端点的数值×2,右端点×2+1后存原创 2021-11-23 15:57:06 · 688 阅读 · 0 评论 -
贪心问题-最大不相交区间数量
问题:https://www.acwing.com/activity/content/problem/content/1112/题目分析 :与最小选点数量题目一样的思路,最小选点数量其实就是最大不相交区间数量,两个区间相交了就一定有相同的选点。先按照左端点排序,再取第一个区间的右端点依次对区间进行判断即可。代码实现:数据范围最大值不超过2e9可以使用int存储数据代码思路使用结构体存储区间,同时重新定义小于号。如果使用pair来存区间端点就不需要重新定义小于号了代码// 使用struc原创 2021-11-22 23:29:04 · 131 阅读 · 0 评论 -
贪心问题-区间选点
题目:https://www.acwing.com/activity/content/problem/content/1111/题目分析:保证每个区间上最少有一个点被选到,首先将所有的区间按照左端点排序从第一个区间开始取右端点,如果下一个区间的左端点小于已经选定的点,则不需要重复选点。如果下个区间的左端点大于已选定的点则选点数加1同时选中该区间的最右端点代码实现数据范围不涉及到数据的运算,数据范围都在 int 范围内,可以直接使用 int 来存储数据了。代码思路使用结构体存储区间的左右端原创 2021-11-22 23:12:53 · 111 阅读 · 0 评论 -
贪心问题-合并果子
题目https://www.acwing.com/activity/content/problem/content/1115/问题分析假设每次合并果子选择最小的两堆合并,总耗费精力最小。方案证明证明方法同排队打水问题,与那个问题的区别在于,合并两个果堆后还会进行重新排序,解决方案更优。每次合并时都是两个最小的果堆。代码实现数据范围题目规定输出数据不会大于231 即刚好不会爆int,使用 int 来储存数据。实现思路典型的Huffman问题,通过小根堆保证每次取值都是数据的最小值。时间复原创 2021-11-22 17:04:44 · 403 阅读 · 0 评论 -
贪心问题-排队打水
题目https://www.acwing.com/activity/content/problem/content/1213/题目分析同样猜想一个方法,假设所有人的时间按照大小排序,打水耗费时间长的最后取。方案证明假设共有 n 个人按顺序依次打水,每个人的取水时间为 ti ,则第一个人的等待时间为0,第二个人的等待时间为 t1 ,第三个人等待的时间为 t1 + t2 同理可得第 n 个人的等待时间为 t1 + t2 +…+tn ,等待时间总和为: tn + 1 × tn-1 + 2 × tn-2原创 2021-11-22 16:37:46 · 309 阅读 · 0 评论 -
贪心问题-货仓选址
题目https://www.acwing.com/activity/content/problem/content/1214/题目分析假设出的解决方案:将所有商店在坐标上排序后取中位数位置放置货舱。如果是奇数个商店则货舱位置为排序后中间位置的商店,如果是偶数个商店则货舱位置为中间两个商店之间的任意位置。方案证明奇数个商店共 n 个商店选中 n/2(向下取整) + 1 个商店为货舱位置后,左边送货的距离总和为 p,右边送货的距离总和为 q,距离总和为 p + q将货舱左移一位,左边送货的距离总和原创 2021-11-22 16:03:23 · 737 阅读 · 0 评论 -
贪心问题-耍杂技的牛
题目https://www.acwing.com/problem/content/127/题目分析该类问题属于贪心问题,首先需要猜一个解决方案。按照牛的重量和强壮程度的总和排序,按照从大到小的顺序依次将牛放置。方案证明假设一共有 n 头牛,从上往下数位于第 i 个位置的牛的重量为 Wi ,强壮程度为 Si ,重量和强壮程度总和为 Wi + Si 。第 i + 1 个位置的牛的重量为 Wi+1 ,强壮程度为 Si+1 ,重量和强壮程度总和为Wi+1 + Si+1 。前置条件:Wi + Si原创 2021-11-21 14:27:43 · 457 阅读 · 0 评论