《算法竞赛进阶指南》0x01

0x00 基本算法

0x01 位运算

算数位运算

​ 与 或 非 (取反) 异或(同为0,异为1)

and,& or,| not,~ xor

补码(-x=~x+1)

32位有符号整数int:以最高位为符号位,0表示非负数,1表示负数;

目的:用加法来实现减法;

等价:一个数与其补码做加减法运算等价于在32位补码下做最高位不进位的二进制加减法运算;

初始化:

int a[maxn];
memset(a,0x3f,sizeof(a));

是将0x3f填充到数组a的每个字节上,一个int有四个字节,所以每个int被赋值为0x3f 3f 3f 3f;

而0x3f3f3f3f是满足以下两个条件的最大整数:

  1. 整数的两倍不超过int的边界0x7f ff ff ff;
  2. 每8位(每个字节)都是相同的;

位移运算

左移(=*2)

11——>110   //低位以0填充
1<<n=2^n  ,  n<<1=2n

右移(=/2)

11——>1     //高位以符号填充,低位越界后舍弃
n>>1=[n/2.0]//[]表示向下取整

a^b

求 aa 的 bb 次方对 pp 取模的值。

输入格式

三个整数 a,b,pa,b,p ,在同一行用空格隔开。

输出格式

输出一个整数,表示a^b mod p的值。

数据范围

0≤a,b,p≤1090≤a,b,p≤109

输入样例:

3 2 7

输出样例:

2

[√] AC:

//快速幂
#include<iostream>
using namespace std;

int main()
{
    int a,b,p;
    cin>>a>>b>>p;
    int ans=1%p;
    while(b)
    {
        if(b&1) ans=ans*1ll*a%p;
        a=a*1ll*a%p;
        b=b>>1;
    }
    cout<<ans<<endl;
    return 0;
}

64位整数乘法

求 a 乘 b对 pp取模的值。

输入格式

第一行输入整数a,第二行输入整数b,第三行输入整数p。

输出格式

输出一个整数,表示a*b mod p的值。

数据范围

1≤a,b,p≤10181≤a,b,p≤1018

输入样例:

3
4
5

输出样例:

2

[√] AC

//乘法变加法
//a*8=4a+4a
//a*(2^k)=2^k*a

#include<iostream>
using namespace std;

int main()
{
    long long a,b,p;
    cin>>a>>b>>p;
    long long ans=0%p;
    while(b)
    {
        if(b&1) ans=(ans+a)%p;
        a=a*2%p;
        b=b>>1;
    }
    cout<<ans<<endl;
    return 0;
}

二进制状态压缩

​ 操作 运算

取出整数n在二进制的第k位 (n>>k)&1

取出整数n在二进制的第0~k-1位 n & ((1<<k)-1)

把整数n在二进制的第k位取反 n xor (1<<k)

把整数n在二进制的第k位赋值1 n | (1<<k)

把整数n在二进制的第k位赋值0 n & (~(1<<k))

最短Hamilton路径

给定一张 nn 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径。 Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。

输入格式

第一行输入整数nn。

接下来nn行每行nn个整数,其中第ii行第jj个整数表示点ii到jj的距离(记为a[i,j])。

对于任意的x,y,zx,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]>=a[x,z]。

输出格式

输出一个整数,表示最短Hamilton路径的长度。

数据范围

1≤n≤201≤n≤20
0≤a[i,j]≤1070≤a[i,j]≤107

输入样例:

5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0

输出样例:

18

[ ] AC


成对变换

当n为偶数时,n xor 1等于 n+1

当n为奇数时,n xor 1等于 n-1

因此“0和1”,“2和3”,“4和5”……关于xor 1形成“成对变换”。

用处:对于图论的邻接表可以用成对变换来存储成对的正向边和反向边。

lowbit运算

lowbit(n)表示n最低位的1及其后边所有的0

lowbit(111001000)=1000

lowbit(n) = n&(~n+1) = n&(-n)
posted @ 2020-07-14 20:22  神奇周一  阅读(400)  评论(0)    收藏  举报