位运算
应用
- 快速幂
- 标记状态 —— 动态规划
- 用异或实现配偶
lowbit
运算
功能 | 示例 | 位运算 | 运算符 |
---|---|---|---|
去掉最后一位 | (101101->10110) | x shr 1 |
x>>1 |
在最后加一个0 | (101101->1011010) | x shl 1 |
x<<1 |
把最后一位变成1 | (101100->101101) | x or 1 |
x|1 |
最后一位取反 | (101101->101100) | x xor 1 |
x^1 |
取末三位 | (1101101->101) | x and 7 |
x&7 |
1 << n
1 左移 n 位 ——> 2n
n >> x
n 右移 x 位 ——> n / 2x
快速幂
求 mk%p,时间复杂度 O(log k)。
int qmi(int m, int k, int p) {
int res = 1 % p, t = m;
while (k) {
if (k & 1) res = res * t % p * 1ll;
// *1ll 将 int 类型转化为 long long
t = t * 1ll * t % p;
k >>= 1;
}
return res;
}
91.最短Hamilton路径
给定一张 n 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短 Hamilton 路径。 Hamilton 路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。
输入格式:
第一行输入整数 n。
接下来 n 行每行 n 个整数,其中第 i 行第 j 个整数表示点 i 到 j 的距离(记为 a [ i , j ] )。
对于任意的 x , y , z ,数据保证 a [ x , x ] = 0,a [ x , y ] = a [ y , x ] 并且 a [ x , y ] + a [ y , z ] >= a [ x , z ]。
输出格式:
输出一个整数,表示最短Hamilton路径的长度。
数据范围:
1 ≤ n ≤ 20 0 ≤ 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
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20, M = 1 << 20;
int mg[N][N], f[M][N];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cin >> mg[i][j];
memset(f, 0x3f, sizeof f);
f[1][0] = 0;
for (int i = 0; i < 1 << n; ++i) //第一层状态为过不过i点
for (int j = 0; j < n; ++j) //第二层状态为终点为j点
if (i >> j & 1) // 判断i的第j位是不是1
for (int k = 0; k < n; ++k)
if ((i - (1 << j)) >> k & 1)
f[i][j] = min(f[i][j], f[i - (1 << j)][k] + mg[k][j]);
cout << f[(1 << n) - 1][n - 1] << endl;
return 0;
}
用异或实现配偶
e[index]
e[index ^ 1]
lowbit
运算
// lowbit(1110010000) = 10000
int lowbit(int n) {
//return (~n + 1) & n;
return (-n) & n;
}