笔记-改
2023-07-30 13:53:26
发布于:广东
截止至27日上午(全打完讨论放不下)
原帖地址
现在这个txt比我复制时多了一倍左右qwq
7月22日上午:
	通俗地讲,算法是解决一系列问题的清晰步骤和方法,是准确解决问题方案的完整描述,
	是对有一点规范的输入,在有限的时间内获得所要求的输出的这种能力的表达。
    	一个合格的算法,具备五个特性:
	    1.有穷性:一个合格的算法必须在执行完有穷(有限)步骤后再结束且有时间限制;
	    2.确定性:算法的步骤规定,含义和执行方法都是非常明确的;
	    3.可行性:所有操作都可实现;
	    4.输入:算法有多个或者零个输入;
	    5.输出:与输入一样,算法有多个或零个输出。没有输出(结果)的算法没有意义;
7月22日下午
	STL:Standard Template Library 标准模板库,一般将这些模板称之为“容器”
	常用容器包括string vector set map queue等。
	vector:容器内元素访问:
	    1.通过下标访问,类似普通数组,下标从0开始
	    2.通过迭代器访问:vector<DataType>::iterator it;
	常用成员函数(设 vector 容器名 val):
	函数名                            功能                                    时间复杂度
	val.push_back(data)	      对val向后插入data数据	O(1)
	val.pop_back()	      删除val尾数据		O(1)
	val.size()	                      当前val内元素个数	O(1)
	val.clean()		      清空当前val容器		O(N)
	val.begin()		      起始迭代器	          	-
	val.end()		      末尾迭代器	         	-
	val.empty()	      判空		 	-
	set:容器内元素访问:
	    只能通过迭代器访问:set<DataType>::iterator it;
	常用成员函数(设 set 容器名 val):
	函数名                             功能                                         时间复杂度
	val.insert(data)	       对val插入data数据	      O(1)
	val.erase(it)	       1.删除一个迭代器it所指的位置    O(1)
                                                       2.删除一个值为it的数据	      O(log(n))
	val.erase(first,last)            3.删除迭代器于[first,last)的数据  O(last-first)
	val.size()		       当前val内元素个数	      O(1)
	val.clean()		       清空当前val容器	         	      O(N)
	val.begin()		       起始迭代器		      -
	val.end()		       末尾迭代器		      -
	val.find(data)	       在val中查找data	         	      O(log(n))
	map:容器内元素访问:
	    1.通过“下标”访问,即键值对访问,例如map['name']。
	    2.通过迭代器iterator访问元素:
	        map<DataType1,DataType2>::iterator it;
	        迭代器指代的是一个键值对对象:
	        用it->first访问键(DataType1),it->second访问值(DataType2)。
	常用成员函数(设 map 容器名 mp):
	函数名                             功能                                         时间复杂度
	mp.erase(it)	       1.删除一个迭代器it所指的位置    O(1)
			       2.删除一个键为it的数据	      O(log(n))
	mp.erase(first,last)	       3.删除迭代器于[first,last)的数据  O(last-first)
	mp.size()		       当前mp内,键的个数                   O(1)
	mp.clean()		       清空当前mp容器                       O(N)
	mp.begin()	       起始迭代器	                      -
	mp.end()		       末尾迭代器                               -
	mp.find(data)	       在mp中查找键data	      O(log(n))
7月23日上午:
	前缀和:
	    前缀和是指一段序列的前n项之和,可以理解为数学中,数列的前n项之和。
	    下标位置  0   1   2   3   4   5   6  
	    数据数组a 0   4   3   2   5   9   6	  
	    数据数组b 0   4   7   9  14  23  29	
	    b[1] = a[1]	        令b[i] = a[1]+a[2]+…+a[i-1]+a[i]
	    b[2] = a[1] + a[2]	则b[i-1]=a[1]+a[2]+…+a[i-1]
	    b[3] = a[1] + a[2] + a[3]……	有b[i] = b[i-1]+a[i]
	区间和:
	    区间和往往是值一段序列连续某段连续区间之和。
	    下标位置	0   1   2   3   4   5   6  	
	    数据数组a	0   4   3   2   5   9   6	    	
	    前缀和数组b	0   4   7   9  14  23  29	
	    推广到[L,R]区间和:ans = a[L]+a[L+1]+a[L+2]+…a[R]
	    可知前缀和h[R]=a[1]+a[2]+…+a[L-1]+a[L]+a[L+1]+…+a[R]
	    整理算式得b[R]=b[L-1]+ans   因此 [L,R]区间和:ans=b[R]-b[L-1]
	差分区间修改:
	    问题表述:
	        对序列区间[L,R]中的每个数都加上c。
	    思路分析:
	        对d[L]增加c将使得a[L]及之后的数据都增加c。
	        对d[L]减少c将使得a[R+1]及之后的的数据减少c。
	        两种操作同时操作 则易知从a[R+1]开始之后的数据
	        因+c-c而无变化。
	    时刻牢记:
	        差分是前缀和的逆运算。
7月23日下午
	递归:
	        根据递归调用自身的位置不同,数量不同,可以将递归执行大致分为:
	            前置递归,后置递归,前后混合递归。
7月23日晚上
	初赛知识点:
	    宏定义
	        #define ll long long
	        在编译时将所有ll替换为long long
		进制转化
			-整数
				除x取余,逆序排列
			-小数
				乘x取整,顺序排列
		原码
			由符号位和数值位表示。符号位为最左边的位,为0表示正数,为1表示负数
			14-0000 1110
			-14-1000 1110
		反码
			反码也是由符号位和数值位表示。符号位为最左边的位,为0表示正数,为1表示负数。正数的原码与反码相同。
		补码
			补码也是由符号位和数值位表示。符号位为最左边的位,为0表示正数,为1表示负数。正数的原码与补码相同,补码等于反码+1。
			-14(原码)-1000 1110
			      反码-1111 0001
			      补码-1111 0010
		位运算
			程序中的所有数在计算机内存中都是以二进制的形式储存的。
			位运算就是直接对整数在内存中的二进制位进行操作。比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算。
			按位与 & - 7&10=0011
			按位或 | - 5|9=1101
			按位异或(相同为0,不同为1) ^ - 5^9=1100
			按位取反 ~
			按位右移(右移一位,高位补零,低位丢弃) >> - 9>>2=0011 (/2的x次方)
			按位左移(右移一位,高位丢弃,低位补零) << (*2的x次方)
7月24日上午
	贪心:
	       贪心算法,又称贪婪算法,是指在对问题求解时,模拟一个“贪心”的人做出决策的过程。
	       在每次做出决策的时候都采用当前看来最好的选择,不从整体最优上去考虑,
	       他所做出的仅是在某种意义上的局部最优解,所以贪心算法不是对于所有问题都能够得到最优解,
                 关键是选择贪心的策略。
	贪心算法需要具备的特征:
	       1.贪心的选择:一个问题的整体最优解,能够通过一系列局部的最优解的选择
	         达到。每次的选择可以依赖以前做出的选择,但不依赖于后面要做出的选择,
	         这就是贪心选择性质
	       2.最优子结构:当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构。
	         问题的最优子结构性质是该问题可用贪心法求解的关键所在。
7月24日下午
	二分搜索:
	    二分搜索,又名二分查找,折半查找。从算法大类来讲,属于分治的策略。
	    经典的二分搜索例子,猜数字。
	    顾名思义,每次将搜索规模缩小一半,因此搜索的时间复杂度为:O(logN)
	二分模版:
寻找x
int binSearch(int a[],int x,int left,int right){
	while(left<=right){
		int mid=(left+right)/2;
		if(x==a[mid]){
			return mid;
		}else if(x>a[mid])
			left=mid+1;
		}else{
			right=mid-1;
		}
	}return -1;
}
大于等于x
int BinarySearch(int b[],int left,int right,int x){
	int midd=-1;
	while(left<=right){
		int mid=(left+right)/2;
		if(b[mid]>=x){
			midd = mid;
			right = mid-1;
		}
		else if(x>b[mid]){
			left=mid+1;
		}
	}
	return midd;
} 
大于x
int BinarySearch(int b[],int left,int right,int x){
	int midd=-1;
	while(left<=right){
		int mid=(left+right)/2;
		if(b[mid]>x){
			midd = mid;
			right = mid-1;
		}
		else{
			left=mid+1;
		}
	}
	return midd;
} 
	函数:所需头文件:#include<algorithm>
	使用前提:递增序列,如递增数组
	作用:
	    lower_bound (a, a + n, x)
                    在[a, a + n)区域内二分搜索第一个大于等于目标值 x 的地址。
	    upper_bound (a, a + n, x)
                    在[a, a + n)区域内二分搜索第一个大于目标值 x 的地址。
	    若该值存在,返回该值的地址,若该值不存在,返回a+n这个地址。
	地址换算为数组中的下标
	    int v = lower_bound (a, a + n, x) - a
	    int v = upper_bound (a, a + n, x) - a
7月25日上午:
7月25日下午:
	归并排序:
	    归并排序,又名二路归并排序。顾名思义,该排序算法涉及了二分的思想
	    即将原数列不断的平均拆分成两个子部分,再分别对子部分分别进行处理。
	    而“并”字,则意味着,将处理好地子部分再有序地合并起来。
	归并排序步骤:
	    (1)令 mid=(R+L)/2 将[L,R]拆为[L,mid]于[mid+1,R]
	    (2)若L < mid,则将[L,mid]作为新[L,R]跳转(1),否则跳转(3)
	    (3)若mid + 1 < R,则将[mid+1,R]作为新[L,R]跳转(1),否则跳转(4)
	    (4)有序合并[L,mid]于[mid+1,R]
归并排序代码:
// 将a数组的 [L1,R1] 和 [L2,R2] 区间元素进行归并 
void merge(int a[],int L1,int R1,int L2,int R2){
	int i=L1,j=L2,cnt=0;
	// 两个范围都没有越界 
	while(i<=R1&&j<=R2){
		if(a[i] <= a[j]) tmp[cnt++] = a[i++];
		else tmp[cnt++] = a[j++];
	}
	// 前半段还有元素 
	while(i<=R1) tmp[cnt++] = a[i++];
	// 后半段还有元素 
	while(j<=R2) tmp[cnt++] = a[j++];
	// 将数组 tmp(0~cnt-1) 复制到数组 a(L1,R2) 
	for(int i=0;i<cnt;i++){
		a[L1+i] = tmp[i];
	}
}
// 将数组 a 区间 [l,r] 的元素进行升序排列 
void MergeSort(int a[],int l,int r){
	// 只有一个元素,无法再划分,返回 
	if(l>=r){
		return;
	}
	// 求中间元素位置 
	int mid = (l+r)/2;
	// 对前半段 [l,mid] 继续递归划分 
	MergeSort(a,l,mid);
	// 对后半段 [mid+1,r] 继续递归划分 
	MergeSort(a,mid+1,r);
	// 归并区间 [l,mid] 和 [mid+1,r] 的元素 
	merge(a,l,mid,mid+1,r); 
}
	快速排序:
		快速排序,简称快排,排序的核心逻辑是拆。但这个拆法于归并排序不同,
                	归并是单纯的拆开,快排是寻找一个基准值val,将数列拆分不小于val的部分
                	和不大于val的部分。然后对两个拆出来的部分重负这个拆分行为,直到
                	不可再拆为止
		1.选择枢纽(一般是序列第一个数)
		2.比枢纽小(大),移到枢纽的前面
		3.比枢纽大(小),移到枢纽的后面
		4.对新的两个子序列,再次重复上述步骤。
		(1.不断将j--,j指向最后一个元素,当i<=j时重复以下步骤
		2.不断将j--,直到a[j]<=key
		3.不断将i++,直到a[i]>=key
		4.如果i<=j,交换a[i]和a[j],i++,j--)
快速排序代码:
void QuickSort(int a[],int l,int r){
	if(l>=r){
		return;
	}
	int key=a[(l+r)/2],i=l,j=r; // key选中间元素 i指向第一个位置 j指向最后一个位置
	// 通过这样一个while就可以将<=key的放在l~i-1 >=key的放在i~r 
	while(i<=j){
		while(a[j]>key) j--; // 从右向左找到第一个<=key的 
		while(a[i]<key) i++; // 从左向右找到第一个>=key的 
		if(i<=j){
			swap(a[i],a[j]);
			i++;j--;
		}
		QuickSort(a,l,i-1);
		QuickSort(a,i,r);
	}
}
	高精度:
	    高精度加法:
	        1.读入和存储
	            输入:
	                string s/char s[]
	            存储:
			        int a[](方便计算/相同数位对齐)
			        s[len-1] = a[0]
			        ......
			2.做加法(进位)
			    1.从个位开始,逐位相加,满10进1
			    2.枚举的范围(c的下标范围)
			        0~lenc-1 lenc=max(len(a),len(b))
			    3.判断最高位的进位情况
			    4.逆序输出
		高精度减法:
			1.读入、比较和存储
			    输入:
			        string s/char s[]
			    比较:
			        若被减数<减数,则交换并输出负号
			        ①比位数,位数多的数大
			        ②位数一样,从高位到低位按位比大小
			    逆序存储:
			        int a[](方便计算/相同数位对齐)
			        s[len-1] = a[0]
			        ......
			2.做减法(借位)
			    1.从个位开始,逐位相加,满10进1
			    2.枚举的范围(c的下标范围)
			        0~lenc-1 lenc=max(len(a),len(b))
			    3.判断最高位的进位情况
			    4.逆序输出
		高精度乘法:
			1.读入存储
			    输入:
			        string s/char s[]
			    逆序存储:
			        int a[](方便计算/相同数位对齐)
			        s[len-1] = a[0]
			        ......
			2.做乘法(进位)
			    a[i+j] += a[i] * b[i]
			    满10向前一位进位
			    先认为结果是两个乘数的的长度的和
			    1.从个位开始,逐位相加,满10进1
			    2.枚举的范围(c的下标范围)
			        0~lenc-1 lenc=max(len(a),len(b))
			    3.判断最高位的进位情况
			    4.逆序输出
		高精度除法:
			1.读入和存储
			    输入:
			        string s/char s[]
			    顺序存储:
			        int a[](方便计算/相同数位对齐)
			        s[i]='0' = a[i]
			        ......
			2.做除法
			    a[i+j] += a[i] * b[i]
			    满10向前一位进位
			    先认为结果是两个乘数的的长度的和
			    1.从个位开始,逐位相加,满10进1
			    2.枚举的范围(c的下标范围)
			        0~lenc-1 lenc=max(len(a),len(b))
			    3.判断最高位的进位情况
			    4.逆序输出
			3.去除前导零
7月25日晚上:
	排列数
	    从n个不同的元素中,任取m个不同的元素按照一定的顺序排成一列,所有排列的个数,叫做从n个不同的元素中取出m个元素的排列数,以A(n,m)表示
	    计算:A(n,m) = n*(n-1)*(n-2)* ... *(n-m+1)
	        分子分母同时乘以(n-m)!
	        A(n,m) = n!/(n-m)!
	组合数
	    从n个不同的元素中,任取m个元素叫做从n各不同元素中取出m个元素的组合
	    从n个不同的元素中取出m个元素的组合数,以*****)表示
	    计算:
	        A(n,m) = n!/(n-m)!
	        *****) = A(n,m)/m! = n!/[(n-m)!*m!]
	    递推式:
	        ①不取第一个元素-从(n-1)个元素取m个元素的组合数C(n-1,m)
	        ②取第一个元素-从(n-1)个元素取(m-1)个元素的组合数C(n-1,m-1)
	        *****) = C(n-1,m)+C(n-1,m-1);
	        -当m=1 从n个中取出1个 C(1,n) = n
	        -当m=0 从n个中取出0个 C(0,n) = C(n,n) = 1
	        -从n个中取出m个与从n个中取出n-m个等价
	        *****) = C(n,n-m)
	    递推方法:
	        用递推的方法求组合数,f[i][j]表示C(i,j)
	        初始状态:f[0][0]=1 f[0][n]=1
	        i=j时:f[i][j]=1
	        其余情况可以递推:f[i][j] = (f[i-1][j-1]+f[i-1][j])
7月26日下午:
	队列:
	   入队操作,是指向一个队列插入新元素。
                    (当head与tail相等时 队列为空)
	   出队操作,是指向一个队列删除队头元素
                   (根据队列的性质,从队头开始删数据,遵循先进先出原则)
	深度搜索:右下左上
7月27日上午:
	记忆化递归:
	    将每次递归的结果以数组存储,不需要每次调用。
全部评论 1
cool
2023-07-30 来自 广东
0









有帮助,赞一个