zoukankan      html  css  js  c++  java
  • 位运算技巧

    位运算是状态压缩DP的基础。

    算符

    C/C++中的位运算算符(按优先级排序):

    红色算符与位运算算符的优先级高低顺序容易弄混,这里强调一下。

    ~ (bitwise NOT) 按位非 ~x

    *  /  %

    + -

    >  >=  <  <=

    <<  >> (bitwise left shift and right shift) 按位左移、右移 x>>y  x>>=y

    == !=

    & (bitwise AND) 按位与 x&y  x&=y

    ^ (bitwise XOR) 按位异或 x^y  x^=y

    | (bitwise OR)    按位或 x|y  x|=y

    基本操作

    1、判断x的第i位      x & 1<<i

    2、将x的第i位置0    x & ~(1<<i)

    3、将x的第i位置1    x | 1<<i

    4、求x的最低位的1           lowbit(x)  x & -x

    枚举子集

    我们知道,可以用一个整型(例如 int、long long)变量 $s$ 表示一个大小不超过该整型位数的全集 $U$ 的某个子集 $S$。现在考虑如何枚举一个用整数 $s$ 表示的集合的所有子集。首先 $s$ 的子集的值必不大于 $s$,所以可以举 $[0,s]$ 的整数,判断其是否为 $s$的子集,复杂度为 $O(s)$。还有一种更好的做法,复杂度为$s$ 的子集个数。

    for(int s=u; ; s=(s-1)&u){
      // do something with s
      if(s == 0) break;
    }

     枚举大小为 $k$ 的子集

    注意:要求 $k > 0$。

    int comb = (1 << k) - 1;
    while (comb < 1 << n) {
        // do sth with comb
        int x = comb & -comb, y = comb + x;
        comb = ((comb & ~y) / x >> 1) | y;
    }

     枚举超集

    for (int s = u; s <= tot; s = (s + 1) | u) {
        // do something with s
    }
  • 相关阅读:
    P2522 [HAOI2011]Problem b(容斥)
    P3455 [POI2007]ZAP-Queries
    P2519 [HAOI2011]problem a(线段树优化dp+思维)
    P2516 [HAOI2010]最长公共子序列 (lcs+容斥)
    [HAOI2010]软件安装(缩点+树形dp)
    P2508 [HAOI2008]圆上的整点(神仙题)
    [SDOI2011]消防(树的直径+二分||单调队列)
    QLabel设置字体颜色
    Qt绘制不规则串口
    C++继承关系
  • 原文地址:https://www.cnblogs.com/Patt/p/4474164.html
Copyright © 2011-2022 走看看