随笔分类 - AcWing
摘要:背包问题可以用dp数组记录最大值。 可以新增另一个数组count,记录等于最大值的方案数, 这样,在算出最大值后,在求解一遍可以以最大值转移过来的方案数的和,即可得到最大值的方案数。 AcWing 11. 背包问题求方案数 代码如下: #include<bits/stdc++.h> using na
阅读全文
摘要:有依赖的背包问题,节点有树形结构的依赖。 可以递归计算。 递归的过程中,首先对节点的每个子树,计算在不同体积下的最大价值,即dp[u][i]。 dp[u][i]代表在节点u的子树中,选择不超过体积i的物品所得到的最大价值。 然后对当前节点,将每个子节点的每个体积看做分组背包问题中的物品求解。 在递归
阅读全文
摘要:二进制优化代码比单调队列优化代码更清晰好写。 可以将一维优化成log级别。 其思想是,将数量s,1+2+4+...+s0,对1、2、4、...、s0分别打包, 则小于s的任意一个数量均可由这些打包表示出来。 这样数量为s的多重背包,可分解为这些打包的01背包。 注意,由于此时物品数量增多,必须优化d
阅读全文
摘要:背包问题求方案时,可以进行dp过后,根据结果进行反推。 要求输出方案时,不能简化dp数组的维数。 当需要以字典序最小输出结果时,可以考虑从后向考虑物品,从后向前构建dp数组。 这样,反推的时候就可以从第一个物品开始考虑,就可以贪心的解决字典序问题。 (也可以使用标记数组解) 例题 AcWing12.
阅读全文
摘要:1、对于体积至多为V 初始化全为0,转移时要求j-v[i]>=0(否则,j<v[i],不可能选) 2、对于体积恰好为V 初始化dp[0]为0,其余为正无穷,转移时要求j-v[i]>=0 3、对于体积至少为0 初始化dp[0]为0,其余为正无穷,转移时不做要求。如果j-v[i]<0,则从0转移(因为如
阅读全文
摘要:例题 AcWing 1010. 拦截导弹 建立最长下降子序列模型。 同时对于最少需要配备的系统数,可以利用贪心法,判断添加新系统还是放入某个旧系统中(若放入旧系统,则选择大于当前导弹高度的最小值,同时可以发现系统当前高度单调上升,可二分)。 AcWing 187. 导弹防御系统 上一题的拓展,由于有
阅读全文
摘要:对AcWing 1015. 摘花生(走一次)的拓展 二维网格,左上到右下走两次,或者左上到右下再到左上,求收集数总和的最大值。 等价于求两条路径,和行走方向是无关的。 故都可以等价为从左上同时走。 例题: AcWing 1027. 方格取数AcWing 275. 传纸条 构建dp的方法是,三位dp,
阅读全文
摘要:多重背包问题可以用单调队列进行优化 原理见:提高课1.3.1 背包模型(一) 离题:6. 多重背包问题 III 单调队列的deque实现如下: #include<bits/stdc++.h> using namespace std; int v[1010]; int w[1010]; int s[1
阅读全文
摘要:1、在图的邻接表存储中,可以使用模拟链表法: const int N,M=2*N; h[N],e[M],ne[M],idx;//链表头/链表结点的序号/链表节点的下一个节点 void add(int a,int b) { e[idx]=b; ne[idx]=h[a]; h[a]=idx++;} 也可
阅读全文
摘要:一、区间问题 1、区间选点、最大不相交区间数量 先按右端点排序,遇到完全不相交的区间则更新当前点,并将区间数量+1. 2、区间分组 将区间分组使组内区间不相交,求分组的最小数量。 左端点从小到大排序,从前往后处理每个区间,判断是否能放入当前的某个组中, 如果能,则更新组的右端点,否则开新组。 3、区
阅读全文
摘要:1、背包问题 (1)01背包 每件物品仅用一次 可以做空间优化 dp[j]=max(dp[j],dp[j-v[i]]+w[i]); 0,1背包状态均是从前一循环的状态转移 注意如果不使用空间优化时,要对小于当前重量的dp位置进行赋值(为上一轮dp的值)!! (2)完全背包 每件物品可以用无限次 dp
阅读全文
摘要:容斥原理:求集合交集的元素个数 Nim游戏:通过异或结果,直接判断游戏先手是否必胜 对于多个集合,可以计算sg函数,推广Nim
阅读全文
摘要:对质数p 根据费马小定理 有a^(p-1)≡1(mod p)(其中的p-1是p的欧拉函数,见数论的欧拉定理) 则a*a^(p-2)≡1(mod p) a^(p-2)≡1/a(mod p) 即有,1/a(逆元)≡a^(p-2)(mod p)
阅读全文
摘要:0和1的排列转化为二维路径 C(n,2n)-C(n-1,2n)=C(n,2n)/(n+1)(卡特兰数)
阅读全文
摘要:一、高斯消元 对矩阵n*n*x=列向量n 枚举每一列(c+,r) 1、找到当前列绝对值最大的行(如果为0则下一列) 2、将当前行与1、中的行的元素交换 3、将当前行的当前列元素化为1 4、利用当前行的元素,将后面行的当前列的元素化为0(先枚举后面的行,后面的行的当前列元素不为0,则每个列都消) 5、
阅读全文
摘要:1、欧拉函数的定义是,φ(n)是1-n中与n互质的数的个数 对n分解质因数得p1^a1*p2^a2*...*pn^an, 则φ(n)=n*(1-1/p1)(1-1/p2)*...*(1-1/pn); 对多个数求欧拉函数,可以结合线性筛法,对每个质数和被筛到的数,都根据已经被循环到的数的φ计算 1 c
阅读全文
摘要:一、质数 质数是大于1的自然数,只包含1和本身两个约数。 1、质数的判定,O(sqrt(n)) 试除法,推荐循环i<=n/i(防止溢出和sqrt计算) 2、分解质因子,O(logn~sqrt(n)) 1 for(int i=2;i<=n/i;i++) 2 { 3 if(n%i==0) 4 {//此时
阅读全文
摘要:一、最小生成树 1、prim算法 和dijkstra算法很像 (1)朴素版 O(n^2) 适合稠密图 dijkstra算法每次更新到起点的距离,prim算法每次更新到集合的最短距离(用邻接点到当前被加入点的距离更新)(集合为已经生成的树) 858 Prim算法求最小生成树 1 #include<io
阅读全文
摘要:最短路问题 一、单源最短路(一个点到所有点的最短距离) 1、所有边的权重都为正 n个点,m个边 (1)朴素dijkstra O(n^2) 适合稠密图,O(n^2)=O(m) 算法步骤: ①初始化距离 dis[1]=0,dis[i]=+∞,集合s为已经找到的点的集合 ② for i=1:n 找到点t,
阅读全文
摘要:图可以用邻接表存储, 邻接表为n个链表, 链表可以用数组模拟(比vector速度快)。 const int N; int h[N],e[N],ne[N],idx;//分别表示,h[i]:图中编号i的头结点,e[i]:节点i的值(编号),ne[i]节点i在链表中的下一个节点的idx。 void add
阅读全文