首页 > 技术文章 > 算法竞赛进阶指南 0x00 简化版

zhao-jq 2021-04-02 14:44 原文

算法竞赛进阶指南 0x00 简化版

0x01 位运算

就几种位运算符,没别的

异或 左移 右移
& | ~ ^ << >>

我们都知道,计算机只能存储2进制数,例如7,在2进制下就是111 。4就是100

  • & 例如 1111&1011=1011 再例如 01101&100=100 也就是1&1=1 1&0=0 0&1=1 0&0=0

  • | 1|1=1 1|0=1 0|1=1 0|0=0

  • ~ ~1=0 ~0=1

  • ^ 1^1=0 1^0=1 0^1=1 0^0=0

  • << 1<<1=10 1<<2=100 101<<2=10100

  • >> 1000>>1=100 1001>>1=100

值得一提的是lowbit运算,这也是树状数组中的一个重要部分,求一个数在二进制下最后一位非0位和它后面的0.

lowbit(111101000)=1000

如何实现呢? 设最后一位非0位是第k位,将 x取反,则0都变成1,1都变成0,1~k-1位均为1,再给它加上1,

1~k-1 位为0,k位为1,在&上个原数,k为后面因为取反肯定是0,1~k-1 位是0是显然的,又由于~x=-x-1

所以lowbit(x)=x&-x

0x02 递推与递归

递推

递归:就是自己调用自己。

0x03 前缀和与差分

1.前缀和:给出数列{\(a_1\ a_2\ a_3\ a_4 \cdots a_n\)}

​ 前缀和

\[\begin{split} s_i=\sum_{k=1}^ia_k\end{split} \]

2.差分:类似于前缀和的逆运算

​ 差分序列的前缀和就只原序列的该数。

0x04二分

​ 就是每次排除一半的答案,

void erfen() 
{
	int l,r,mid;
	while(l<r)
	 {
		int mid=(l+r)><1;
		if(a[mid]>=x) r=mid;
		else a=mid+1;
	}
	return a[l];
}

代码很容易理解。

0x05排序

排序

事实上,只要会sort就行,其他的基本用不上

0x06 倍增

待填坑

0x07 贪心

算法比较简单,主要是要知道什么时候该用,什么时候不该用。

几种常用的方法:

  1. 微扰(邻项交换):证明任意情况下,局部最优的微小改变会使总体结果变差

  2. 范围缩放: 证明局部最优解就是整体最优解

  3. 决策包容性:这个局部最优策略提供的可能性包含其他所有策略提供的可能性

  4. 反证法

  5. 数学归纳法

    0x08 总结与练习

    acwing

推荐阅读