算法竞赛进阶指南 0x00 简化版
算法竞赛进阶指南 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 贪心
算法比较简单,主要是要知道什么时候该用,什么时候不该用。
几种常用的方法:
-
微扰(邻项交换):证明任意情况下,局部最优的微小改变会使总体结果变差
-
范围缩放: 证明局部最优解就是整体最优解
-
决策包容性:这个局部最优策略提供的可能性包含其他所有策略提供的可能性
-
反证法
-
数学归纳法
0x08 总结与练习