位运算相关技巧

主要是状态压缩中会遇到的一些问题。

基础运算

  • 与 ($\ \&\ $):有0就0
  • 或 ($\ |\ $):有1就1
  • 异或 (^ 或者 \(xor\)):同0异1
  • 非(取反) ( ~ ) :0变1,1变0
    注意:在符号型整数\((int,long\ long)\)下进行按位取反运算会使得最高位(也就是符号位)也取反,并使数值加1,如\(\\~6=-7\).

联系应用

按位位运算的特点:独立性,即只改变整数二进制表示下的某位,并不影响其他位.

异或:常与trie(字典树)结合,把整数二进制表示下的各位压进trie上,在trie上进行按位操作. 如:最大异或对,最长异或路径

初始化

空位赋值为1

常见的状压都是通过用‘1’来表示节点已使用,但也有些题会结合lowbit,让我们把空位设为‘1’以取出能用的空位.(如:数独)

我们可以采用以下初始化方法:

n=(1<<x)-1

以此将n的左x位全设为1.

memset

  • 赋值为正无穷

memset(f,0x3f,sizeof(f));

  • 赋值为负无穷

memset(f,0c3f,sizeof(f));

状压操作

对于一个整数n的二进制表示(^为异或):

  • 取出第k位

(n>>k)&1

  • 取出后k位 (与初始化类似的思想)

n&((1<<k)-1)

  • 第k位按位取反

n=n^(1<<K)

  • 第k位赋值为1

n=n|(1<<K)

  • 第k位赋值为0

n=n&(~(1<<K))

lowbit

lowbit(n)表示取出n在二进制表示下最低位的‘1’及其后面的0.

如:\(6_{(10)}=110_{(2)}\),则\(lowbit(6)=10_{(2)}=2_{(10)}\)

可以用来找出n在二进制表示下所有是‘1’的位,也是树状数组的基础.

  • 具体操作:

$ lowbit(n) = n \& (-n) $

若要取出所有是‘1’的位的位置,则先用Hash预处理\(log_2\),使得\(lg[1<<x]=x\);如lowbit(n)取出\(100_{(2)}=1<<3\),则最低位的‘1’在第三位

注意:位置从0开始,如\(110_{(2)}\),最低位位置为1

每次取出lowbit(n)后减去它,使当前最低位的‘1’前移.

  • 代码实现:
int n,lg[(1<<20)+1];
void lowbit()
{
    for(int i=0;i<=20;i++) lg[1<<i]=i; //预处理
    while(n){
        cout<<lg[n&(-n)]<<endl; 
        //输出当前最低位‘1’的位置,如110(2)输出1
        n-=n&(-n);
    }
}
posted @ 2025-10-31 23:27  Cheese_XD  阅读(0)  评论(0)    收藏  举报