位运算 学习笔记

位运算

应用

  • 快速幂
  • 标记状态 —— 动态规划
  • 用异或实现配偶
  • 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;
}

猜你喜欢

转载自blog.csdn.net/qq_46039856/article/details/113307987