自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(70)
  • 收藏
  • 关注

原创 自学数学应该学什么

基础课程数学分析推荐科目:入门教材 An Intuitive and Physical Approach 第二版深入学习推荐 Richard Courant, Fritz John, Introduction to Calculus and Analysis(Reprint of the 1989 edition)我并没有选择这两本作为入门,因为我已经学过高等数学了,这里我选择...

2019-11-01 21:52:03 313

翻译 romantic math

Collatz猜想随意选一个整数,如果它是偶数,那么将它除以 2;如果它是奇数,那么将它乘以 3 再加 1。对于得到的新的数,重复操作上面的运算过程。如果你一直操作下去,你每次都终将得到 1。数学家们试验了数百万个数,至今还没发现哪怕一个不收敛到 1 的例子。然而问题在于,数学家们也没办法证明一定不存在一个特殊的数,在这一操作下最终不在 1 上收敛。有可能存在一个特别巨大的数,在这一套操作下...

2019-10-31 22:10:26 118

原创 C++字符串操作函数

关于string.h,cstring和string的区别:string.h 是C版本的头文件,包含比如strcpy、strcat之类的字符串处理函数。cstring 在C++标准化(1998年)过程中,为了兼容以前,标准化组织将所有这些文件都进行了新的定义,加入到了标准库中,加入后的文件名就新增了一个”c”前缀并且去掉了.h的后缀名,所以string.h头文件成了cstring头文件。所以,s...

2019-10-10 16:41:10 374

原创 C++STL日积月累

sort()函数用法①Sort函数包含在头文件为#include的c++标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的,只要出现我们想要的结果即可!②Sort函数有三个参数:(1)第一个是要排序的数组的起始地址。(2)第二个是结束的地址(最后一位要排序的地址)(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序...

2019-10-10 16:19:01 126

原创 三个学生猜数字

问题描述一个教授逻辑学的教授,有三个学生,而且三个学生均非常聪明! 一天教授给他们出了一个题,教授在每个人脑门上贴了一张纸条并告诉他们,每个人的纸条上都写了一个正整数,且某两个数的和等于第三个!(每个人可以看见另两个数,但看不见自己的) 教授问第一个学生:你能猜出自己的数吗?回答:不能 问第二个,不能 第三个,不能 再问第一个,不能 第二个,不能 第三个:我猜出来了,是144! 教授很满意的笑了...

2019-09-24 19:56:33 2166

转载 VScode配置C++支持C++11

通过这两个博客可以比较深刻地理解为什么要配置launch.json文件,以及为什么要配置tasks.json文件参考1参考2

2021-07-13 16:28:45 450

原创 dp的刷表法和填表法

刷表法和填表法  实际上我们实际编写代码的过程中也都有遇到,其实就是一个思想的正反两种思考的过程。填表法值得其实就是dp递推过程中,我们采用填充某个位置的方式来递推,刷表法则指的是,用当前这个状态来推导出所有可能涉及到的状态值。  这两个操作本质上其实是一样的,但是某些情况下不同的选择却会有一些不同的代价开销,以及实现的难度,所以我们要针对具体问题设计合理的实现算法。...

2021-04-22 11:46:16 433

原创 枚举算法

指数枚举  所谓指数型枚举,实际上指的是子集枚举问题,通常有两种枚举方式。①递归枚举#include<bits/stdc++.h>using namespace std;int num[16];vector<int> ans;int n;void dfs(int k){ if(k==n+1){ for(int i=0;i<ans.size();i++)cout<<ans[i]<<" ";cout<<e

2021-04-21 17:19:23 412

原创 单调栈和单调队列的本质区别

栈和队列  栈个队列的区别我们都知晓,栈是只有一端可以插入和删除的线性表,它是一个先进后出的结构,而队列则是有两个端口可以分别进行插入和删除,满足先进先出的特性。  但是实际情况中,我们维持的单调栈与栈的数据结构式吻合的,而维持的单调队列则大部分可能都是双端队列,那么看到一个问题,我们如何确定到底使用来个结构来维持一个单调的序列的?单调栈  我想有很多小伙伴其实也不明白,有时候看着直到要使用单调序列来求解,但是却不直到到底用的是单调栈还是单调队列,这就给人一种隔着一层膜,但是始终都捅不破的感觉,这里

2021-04-21 11:39:22 1158

原创 大数乘法

大数乘法对于两个大数a,b相乘,我们可以将b按照二进制分解的方式分解成为一个系数为0,1的多项式,然后,分别按照从低到高位与a相加取模即可,同时b的位数没增加一位,a则翻倍。code64位整数乘法#include<bits/stdc++.h>using namespace std;long long mul(long long a,long long b,long long mod){ long long ans=0; //还是按照二进制指数分解, //将b

2021-04-01 16:42:36 112

原创 判断二分图

二分图图中没有奇圈,那么该图是一个二分图。判断一个图是不是二分图,只需要判断图中是否存在一个奇圈即可。DFS染色判断二分图原理很简单,就是采用DFS+染色的方式,如果发现相邻的两个点的颜色一样,那么我们返回改图不是二分图,否则返回是二分图。例题关押罪犯#include<bits/stdc++.h>using namespace std;const int N=100010;const int M=200010;int edge[M];int nest[M];int l

2021-03-27 22:11:34 321

原创 强连通分支

强连通分支有向图中,如果一个点集中所有点对之间都可以相互到达,那么这个点对组成的极大集合就叫做强联通分支。求解强联通分支的方法这里介绍两种。两边DFS法主要的依据就在于,一个强联通分支中的点都是可以互相到达的,那么当我们翻转图中的边的方向后,我们就可以得到一个逆图,在这个新的图中,强联通分支不变,如果我们把强连通分支看做一个缩点,那么只要我们按照拓扑逆序遍历即可得到所有强连通分支,而如何求解拓扑排序,实际上有一种DFS遍历的方法,即DFS遍历完成节点的逆序就是拓扑序列。这样我们只需要一遍DFS求出

2021-03-27 15:19:07 2907

原创 C++运行时多态简单介绍

多态  多态与继承时相辅相成的, 将父类定义为一个抽象类,子类可以通过继承的方式定义自己的类,这就是所谓的继承和多态,多态是在运行时编译的,且右基类指针指向子类对象,不能相反,这样基类指针可以在具体实例化的时候表现出各种各样的多态性质。也即使用什么对象来初始化基类指针所指对象,那么该基类指针指向的对象就是什么对象,这就是多态。  构造函数不能是多态,因为虚函数需要一个虚指针vptr指向,但是这个指针是在对象调用调用构造函数时才生成的,时间顺序上不合适。同时从多态的角度考虑,虚函数主要实现运行时多态,通过

2021-03-24 20:54:30 629

原创 网络流算法

网络流最大流算法网络流是图论里面最难,也只最有有魅力的分支,事实上图论中很多问题都可以转化为求解最大流的问题,比如说求解最小割的问题,使用网络流算法会使得求解最小割的时间复杂度降低很多,并且网络流算法还具有很大的普适性。这里我就不多介绍网络流是什么了,相信关于网络流的具体模型,定义有很多科普文章进行了详细的介绍,这里只是给出两种具体的实现算法,以及思想原理。Edmonds-Krap算法  该算法是一种在网络流残余图上寻找增光路的算法,寻找增广路的过程其实就是DFS或者BFS从源点搜索图都可以,但是关

2021-03-24 11:35:58 1991

原创 C++11多线程编程

C++11多线程特性  C++11的新标准引入了std::thread后,我们就可以直接在语言层面编写多线程了,增加了程序更好的移植性。  C++11新标准中引入了四个头文件来支持多线程:atomic和atomic_flag原子操作以及与C兼容的原子操作thread多线程mutex互斥信号量,此外还包括lock_guard以及unique_lock等加锁解锁函数。condition_variable和condition_variable_any条件变脸相关的信号量promise和pa

2021-03-19 20:50:57 195

原创 割边+割点tarjan算法

割点  连通图中删去改点后,剩余的图变得不再连通,那么被删去的点就是割点,求解无向图中的割点我们可以使用tarjan算法在一次DFS内解决。  按照我的理解tarjan算法的思想实际上就是点标号,这里点有两种标号,分别是dfn表示第一次遍历时的标号,而low则将同一个环上的点标成相同的号,在DFS 过程中如果图中存在环,那么一定存在某个时刻,一个点会遍历到dfn小于自己的点,那么在返回的时候,我们将所有环上的点的low值都设置成发现环的那个点的dfn的值,low值小于自身dfn值的点,一定存在于某个环中

2021-03-16 17:25:40 191

原创 树上差分

树上差分  树上差分是我认为是LCA的一种应用方式,由于树的特性,我们在求解树上差分时是能从底向上求解,这样树上差分的适用范围有了一定的限制,例如我们在求解过程中只有子树和的统计才是有意义的,单纯统计一条边上的和是没有任何意义的,这是我们在更改时就只更改了从节点到LCA这一区间的值,对于从别的分治来的统计和,只能代表从这从这一分支向上传递的更改。  树上差分适用于这种问题——对树上的一段路径进行操作,并询问某个点或某条边被经过的次数,此时我们可以利用树上差分实现懒惰更改,并在最终求结果时,采用DFS一次

2021-03-15 21:29:23 734

原创 树的直径

数的直径  所谓树的直径指的是树中所有点对之间距离的最大值,我们有两种O(N)的方法可以求解树的直径,实际情况中我们可以视情况选择;例题树的直径两次BFS  两次遍历的实现在思想上比较简单,我们可以通过反证法证明结论的正确性,由于图的结构是树,所以我们可以使用BFS或者DFS,不影响结论的正确性。#include<bits/stdc++.h>using namespace std;//树的直径两次BFS或者两次DFS实现const int N=2000010;const i

2021-03-14 23:46:47 77

原创 最短路

单元最短路  所谓单元最短路就是以图中某一点作为源点,求该点到所有其他点的最短路的问题。  主要要Dijkstra算法和bellman-Ford两种算法,其中bellman-Ford算法的扩展剪枝版本SPFA算法的实际使用效果可能在某些图中效果很好。例题Dijkstra算法求单元最短路  Dijkstra算法只适合求解边权不为负数的问题。#include<bits/stdc++.h>using namespace std;int edge[200010][3];int las

2021-03-13 17:01:30 76

原创 计数类DP

计数类DP  所谓计数类DP就是常说的统计可行解数目的问题,区别于求解最优解,此类问题需要统计所有满足条件的可行解,而求解最优值的DP问题往往只需要统计子问题时满足不漏的条件即可,但是计数类DP需要满足不重不漏的条件,是约束更高的。  最常见的计数类DP问题就是上楼梯的问题,我们要求解此类问题一个重要的点就是如何划分子问题,然后做到不重不漏,大部分情况下我们想到的方法,同一个解可能会被多次统计,这是不合理的。此类问题也常常与组合数结合到一起,我们可能需要用到数学中组合数的概念,所以如何快速实现组合数,也

2021-03-12 17:33:36 769

原创 组合数计算

组合数计算  模同余条件下的组合数在很多算法中经常用到,因为组合数要用到数的除法,而模同余对除法并不适用,所以我们先要将分母转化为模p的乘法逆元,这样我们就可以将除法转化为乘法,从而快速求解出问题的模同余意义下的解。  根据费马小定理,有a^(p-1)=1mod p,所以a在模p下的乘法逆元就是a^(p-2),由于乘法在模运算下,是可以先做模运算,再做乘法的。模板#include<bits/stdc++.h>using namespace std;long long jc[1001

2021-03-11 21:11:22 134

原创 DP斜率优化

DP斜率优化  DP斜率优化,实际上就是以斜率作为比较的基准,使用单调队列优化的方法,使用斜率优化的问题应当具有这样的特征——状态转移方程是一个关于dp[i]和dp[j]的线性方程,也即dp[i]与dp[j]具有线性关系。  这样我们在求解dp[i]时,实际上就是求解一个点(dp[j],j),使得过该点的dp[i]的值最小,由于斜率是固定的,这导致我们只需要寻找与dp[j]的点形成的凸包相切的那一点作为最优转移点即可,实际求解过程中,我们只需要用单调队列维持边界上的点,再用二分查找的方式确定相切的点即可

2021-03-09 16:02:13 489

原创 C++面试基础知识总结

数据结构排序算法查找算法图遍历算法其他算法二叉搜索树二叉搜索树,也叫二叉查找树(Binary Search Tree,BST),特性是每个结点的值都比左子树大,比右子树小。是单调递增序列。主要目标实现增删查改。C++版本实现在这里插入代码片平衡二叉树...

2021-03-08 22:57:53 73

原创 DP+单调队列优化

单调队列优化  使用单调队列优化的题目具有这样的特点,他需要我们维持一段区间内的某个最优值,这个区间是随着遍历的顺序变化的,但是其变化一定具有这样的特性,也即维持的区间左右端点一定是单调递增的,而不能出现回流的现象,否则我们在维持队列单调性过程中剪枝的数据可能是新的区间中的最大值。  维持区间最优值的方法有很多,例如静态算法ST算法,动态更新区间最值的线段树等等,对于区间左端点或者右端点不单调递增的区间最值问题,我们一定只能使用线段树优化,而不能使用单调队列,我们也可以根据这个特性快速地判断到底使用什么

2021-03-06 21:46:11 235

原创 LIS一维、二维、三维扩展

LIS问题介绍  LIS也就是求解最长上升子序列的问题,最朴素的LIS问题的时间复杂度可以优化到O(nlogn)两种优化方式,一种是采用数据结构,一种是维持一个单调递增的数组,二分查找替换即可,该方法本质是一种贪心的思想。一维例题最长上升子序列二分+贪心优化(单调数组优化)#include<bits/stdc++.h>using namespace std;int main(){ int n; scanf("%d",&n); int num[n];

2021-03-04 15:07:47 554 1

原创 状态压缩DP

状态压缩DP  状态压缩动态规划,是动态规划中非常重要的一类,在动态规划问题中,我们为了表示某个状态,我们需要额外的信息,某些状态我们只需要线性地增加开辟的空间即可,但是某些问题却需要保存一个集合作为当前阶段的状态信息,为了减少对集合信息表示所造成空间和时间复杂度的浪费,我们这里可以用状态压缩的方式来降低空间复杂度;  所谓状态压缩就是用以为K进制的数来表示原始状态空间中一个维度上所有可能的结果,集合中有多少元素,就可以使用多少位的K进制元素来表示这个集合,这就是所谓的状态压缩。例题蒙德里安的梦想

2021-03-03 12:03:07 119

原创 DP后效性处理方法

后效性DP  从一开始学习DP我们就知道,阶段是DP的三大要素之一,也即要想使用DP则需要保证阶段之间无后效性,也即DP的状态图中不能存在环,但是有些问题在我们抽象出状态转移方程后,却发现这道类似动态规划问题的DP题目却不满足无后效性这一基本条件——部分状态之间的转化相互影响,相互转移构成了环形,无法确定出一个何时的DP阶段,从而沿着某个方向递推。  实际上我们可以将动态规划的各个状态看做是未知量,状态转移看做若干个方程,而这若干个方程与未知量的个数相同,那么我们就可以用求解方式的方式求解出各个状态的值

2021-03-02 22:28:17 869

原创 windows命令行Ping命令使用总结

Ping命令简介ping命令是用来测试网络连接,网络速度,以及网络中路由跳数等信息的使用命令,在我们测试网络连接情况,相应时间时具有很好的用处,特别是当我们需要做网络方面的实验时,我们使用Ping命令可以轻松获得一些比较符合实际情况的数据。Ping常用命令首先我们可以使用快捷键win+r打开命令行,也可再开始菜单的运行栏中搜索cmd打开,操作结果如下图:我们输入ping /?可以得到ping的一些常用命令:以ping百度为例,我们分析一下返回值的意义:**分析:**上例中发送了4个32字节

2021-03-02 20:06:50 5697

原创 高斯消元

高斯消元  所谓高斯消元就是求解线性方程组的一种方法, 学过线性代数的人应该对该方法比较清楚,其实与我们求解多元一次方程的方法类似,而高斯消元则是采用矩阵消元的方式求解线性方程组的解。  实现的思想很简单,但是步骤却比较繁琐,我们可以用一个二维矩阵来存储线性方程组中的系数,而用一维矩阵存储常数项,最后按照线性代数中将增广矩阵化简为阶梯型矩阵的方式,来求解出线性方程组的解。例题球形空间产生器#include<bits/stdc++.h>using namespace std;int

2021-03-01 19:57:26 119

原创 环形DP

环形DP  在给定数据是环形数组时,我们求解时要将环形变化为线性数组求解,这里有两种常用的变换方式,下面通过例题给出。例题1  通过对某些特殊位置进行不同初始化,多次DP求解最优解。  休息时间//环形DP//通过一定的手段将环形DP转化为线性DP的问题//本题通过两次DP和错位补充的手段来解决问题#include<bits/stdc++.h>using namespace std;int main(){ int n; int b; scanf("%

2021-02-28 22:42:10 981

原创 树形DP

树形DP  树形DP是一种非线性的DP方式,但是我们可以将一个树按照后序遍历的形式排序(拓扑排序),转化成一个线性DP问题,当然我们也可以直接在树形结构上求解该问题;求解树形DP的方式通常是采用递归的方式,我们需要先递归求出每个子树代表的子问题的解,再在回溯时由子问题推导出当前问题的解,DP的阶段可以选则为一层一层的树节点由深到浅的顺序。  实际上树形DP与记忆化搜索很相似,都是按照DFS序来进行DP的过程,子问题都是DFS搜索过程中产生的各个子树,区别在于,记忆化搜索还可以从上到下记录,树形DP则通常

2021-02-28 09:32:58 89

原创 线性DP

线性DP  具有线性阶段划分的动态规划算法统称为线性DP;  线性DP与数学中的线性空间概念类似,如果一个动态规划的状态包含多个维度,但是在每一个维度上都具有线性变化的阶段,那么该动态规划算法称为线性DP。  常见的如LIS,LCS等都是线性DP的经典问题。例题杨老师的照相排列#include<bits/stdc++.h>using namespace std;int main(){ //好题目啊,线性DP的经典题目 while(true){ i

2021-02-19 14:45:05 412

原创 动态规划

动态规划  动态规划是利用问题的可划分性,以及子问题之间的相似性来降低求解复杂度的方法。动态规划将原问题视为若干个重叠子问题的逐层推进,每个子问题的求解都是一个阶段,在完成前一阶段的计算后才可以进行下一阶段的计算。  形象地讲,动态规划将一个构成问题解得连续序列划分成了一个一个阶段,这样我们可以在阶段的基础上统计到达当前阶段时的最优解,类似于我们学习组合数学时,将加法统计转化为乘法统计的过程。  举个例子吧,投掷一枚骰子两次,总共有多少种不同的可能,按照搜索的思想,我们每次都完整地搜索到一种可能的状态

2021-02-17 08:18:33 200

原创 位压缩的常数级优化

位压缩  位压缩是通过k进制的一位来表示数据中一个状态的一种存储压缩方式,它可以在常数级上优化一个算法,例如我们通常所说的状态压缩动态规划,就是用二进制中的一位来表示所求问题中的一个中间状态,当然这样描述还是比较抽象的。  换个例子,对于一个图来说,如果我们只关心两个边之间的相邻关系,那么我们实际上可以用一个二进制位来表示,用0,表示两点之间没有边,而用1表示两点之间存在一条边,那么我们就可以用一个长的二进制串来表示某一点与其他所有点的相邻关系,而二进制串的长度就是所有顶点的个数。这样就比我们直接使用二

2021-02-16 13:08:28 421

原创 线段树

线段树  相比于树状数组只能解决计算前缀和的问题,线段树则更为通用,我们可以用线段树实现树状数组所有的功能,但是线段树实现较为复杂,通常可以直接套用模板,再针对具体问题做一些变化,这里不再赘述;  线段树利用冗余存储的方式来加快搜索速度,这是时间与空间折中的经典思想;线段树的形状是一颗完全二叉树,其深度为log2(n)取上整,算下来所有线段树中的节点数不会超会数据个数的4倍,这样我们就可以在初始化时直接设置为原始数据数目的4倍即可;  下面给出一个模板以及例题:线段树模板  相对而言递归实现更容易

2021-01-23 21:07:39 73

原创 树状数组

树状数组  树状数组将二进制的特点利用到了极致,这是我们处理程序问题时采用的一个非常经典并且巧妙的方法;  我们仔细分析一下树状数组的特点就可以非常清晰地了解树状数组的工作原理;  首先考虑到传统的我们计算前缀和的方式,我们用num数组保存原始数组,而用sum数组保存前缀和,当我们对num数组中的某个数进行更新时,我们更新的时间复杂度为O(1),但是更新sum数组的时间复杂度却要达到O(n),这样,当更新的操作次数为m时,时间复杂度为O(n*m);  那么我们如何减少每次更新的时间复杂度呢?这里就用

2021-01-23 17:34:49 84

原创 tarjan算法详解

强连通分量  首先简单介绍一下强连通分量的概念,简单点说就是一个有向图里面,强连通分量里面任意两个点之间的可以互相抵达,则这些点和边组成的子图是一个强连通分量。tarjan算法  网上搜到的算法讲解都是将该算法描述为一个缩点的过程,但是具体讲解时却总是感觉很乱,其实可以更加简单地描述该算法,我的想法本质上与缩点其实是一致的,但是我更愿意将tarjan算法的过程描述为一个将同一个强连通分量上的点打上相同标记的算法。  我们只要理解了强连通分量在图中到底意味着什么,tarjan算法其实就迎刃而解了,那强

2021-01-23 15:08:57 338

原创 博弈论与SG函数

NIM博弈  给定n堆物品,第i堆物品有Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可以把一堆取光,但是不能不取。取走最后一件物品者获胜。两人都采用最优策略,问先手能不能获胜;  上面的博弈过程中,第一个行动的人称之为先手,第二个行动的人称之为后手,博弈的中间状态称为局面,而采用最优策略指的是,在当前面临的状态下选择某一步会使得在后续采用最优决策的情况下使得自己一定能够获胜的局面,否则一定失败;  那么如何判断在某一种状态下到底是先手获胜还是后手获胜呢?  显然从原问题到最终问题是

2021-01-22 17:19:17 157 1

原创 素数筛

埃氏筛 &emap;简单来说就是从质因子从小到大扩散,筛选出合数,最终剩余的数就是质数;  有一点优化就是对于小于x^2的来说,由于从2到x-1已经被筛选过,所以此时小于x^2的x的倍数一定已经被筛到过,所以可以跳过;  埃氏筛已经是一个比较优秀的算法了,其时间复杂度是接近线性时间复杂度,大多数程序竞赛问题也可以用埃氏筛解决;codeint vise[1000001];void prime(int n){ memset(vise,0,sizeof(vise)); for(int i=

2021-01-21 22:20:13 237 2

原创 IDA*算法

IDA*算法简介  A算法是在BFS的基础上实施的,这需要维持一个优先级队列,且编程复杂,基于此我们想到是不是可以用DFS+估价函数的形式来进行快速搜索,由于DFS是深度优先的,所以如果估价函数引导下搜索方向不正确时,可能会导致额外的搜索代价,基于此我们可以尝试类似BFS思想的迭代加深的DFS加以辅助配合,这样我们就得到了IDA算法;  IDA算法实际上就是迭代加深DFS+估价函数的形式,我们可以在每一步搜索扩展出的状态中选择估价函数+当前代价最优的进行扩展,当然我们也可以利用估价函数与当前代价的和进行

2021-01-21 16:53:18 1133

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除