竞争编程的按位技巧详细指南

2021年4月13日09:36:21 发表评论 622 次浏览

建议参考关于按位运算符的有趣事实作为前提条件。

1.如何设置数字" num":

如果我们想在数字" num"中的第n个位置设置位, 可以使用" OR"运算符(|)完成。

  • 首先, 我们通过(1 << n)将" 1"移位到n位
  • 然后, 使用" OR"运算符将位设置在该位置。使用" OR"运算符是因为即使先前未使用数字" num"的二进制表示来设置该位, 也会设置该位。
#include<iostream>
using namespace std;
//num is the number and pos is the position 
//at which we want to set the bit.
void set( int & num, int pos)
{
      //First step is shift '1', second
      //step is bitwise OR
      num |= (1 <<pos);
}
int main()
{
      int num = 4, pos = 1;
      set(num, pos);
      cout <<( int )(num) <<endl;
      return 0;
}

输出如下:

6

我们已通过"通过引用致电"传递参数, 以永久更改号码。

2.如何取消/清除数字" num"中第n个位置的位:

假设我们想将数字" num"的第n个位置取消设置, 那么我们必须借助" AND"(&)运算符来实现。

  • 首先, 我们通过(1 << n)将移位" 1"移至n位置, 而不是使用按位NOT运算符"〜"取消设置此移位的" 1"。
  • 现在, 清除此左移的" 1", 即使其变为" 0"后, 我们将对" AND"(&)与数字" num"进行设置, 该数字将在第n个位置保留未设置的位。
#include <iostream>
using namespace std;
//First step is to get a number that  has all 1's except the given position.
void unset( int &num, int pos)
{
     //Second step is to bitwise and this  number with given number
     num &= (~(1 <<pos));
}
int main()
{
     int num = 7;
     int  pos = 1;
     unset(num, pos);
     cout <<num <<endl;
     return 0;
}

输出如下:

5

3.在第n个位置切换一点:

切换意味着如果先前将其设为``off''(0), 则将其设置为``on''(1), 如果先前将其设为``on''(1), 则将其设置为``off''(0)。我们将在此处使用``XOR''运算符是这个" ^"。 " XOR"运算符背后的原因是由于其属性。

  • " XOR"运算符的属性。
    • 1 ^ 1 = 0
    • 0 ^ 0 = 0
    • 1 ^ 0 = 1
    • 0 ^ 1 = 1
  • 如果两位不同, 则" XOR"运算符将返回一个设置位(1), 否则将返回一个未设置的位(0)。
#include <iostream>
using namespace std;
//First step is to shift 1, Second step is to XOR with given number
void toggle( int &num, int pos)
{
     num ^= (1 <<pos);
}
int main()
{
     int num = 4;
     int pos = 1;
     toggle(num, pos);
     cout <<num <<endl;
     return 0;
}

输出如下:

6

4.检查第n个位置的位是否已设置或未设置:

使用" AND"运算符很容易做到。

  • 左移" 1"到指定位置, 然后左移" AND"("&")。
#include <iostream>
using namespace std;
  
bool at_position( int num, int pos)
{
     bool bit = num & (1<<pos);
     return bit;
}
  
int main()
{
     int num = 5;
     int pos = 0;
     bool bit = at_position(num, pos);
     cout <<bit <<endl;
     return 0;
}

输出如下:

1

请注意, 我们首先左移了" 1", 然后使用" AND"运算符将其移到了该位置。因此, 如果" num"中" pos"位置的位置为" 1", 则在" AND"之后, 变量" bit"将存储" 1", 否则如果数字" num"中位置" pos"的位置为" 0"比"与"之后我们的变量位将存储" 0"。

一些更快速的技巧:

  • 反转数字/ 1的补数的每一位:

    如果要反转数字的每一位, 即将位" 0"更改为" 1", 将位" 1"更改为" 0"。可以在"〜"运算符的帮助下进行此操作。例如:如果数字为num = 00101100(二进制表示), 则"〜num"将为" 11010011"。

这也是" 1的数字补码"。

#include <iostream>
using namespace std;
int main()
{
     int num = 4;
  
     //Inverting every bit of number num
     cout <<(~num);
     return 0;
}
Output:
 -5
  •  数字的两个补码:2的数字补数就是1的补数+ 1。

因此, 形式上我们可以找到2的补码, 方法是找到1的补码, 然后在结果中加1, 即(〜num + 1), 否则我们可以做的就是使用"-"运算符。

#include <iostream>
using namespace std;
int main()
{
     int num = 4;
     int twos_complement = -num;
     cout <<"This is two's complement " <<twos_complement <<endl;
     cout <<"This is also two's complement " <<(~num+1) <<endl;
     return 0;
}

输出如下:

This is two's complement -4
This is also two's complement -4
  • 剥离最低设置位:

在许多情况下, 我们想要剥离最低的设置位, 例如在Binary Indexed树数据结构中, 将一个设置位的数量计数。

我们做这样的事情:

X = X & (X-1)

但是它怎么工作?

让我们来看一个例子, 让X = 1100。

(X-1)会将所有位取反, 直到遇到最低位" 1", 并且还要反转最低位" 1"。

X-1变为1011。将X与X-1"与"后, 我们去除了最低的置位比特。

#include <iostream>
using namespace std;
void strip_last_set_bit( int &num)
{
     num = num & (num-1);
}
int main()
{
     int num = 7;
     strip_last_set_bit(num);
     cout <<num <<endl;
     return 0;
}

输出如下:

6
  • 获取数字的最低设置位:

这是通过使用表达式'X&(-X)'完成的, 让我们看一个例子:让X =00101100。因此〜X(1的补码)为'11010011', 2的补码为(〜X + 1或-X), 即" 11010100"。因此, 如果我们将原始数字" X"与两个补码" -X"进行"与"运算, 则会得到最低的设置位。

00101100
& 11010100
-----------
00000100
#include <iostream>
using namespace std;
int lowest_set_bit( int num)
{
     int ret = num & (-num);
     return ret;
}
int main()
{
     int num = 10;
     int ans = lowest_set_bit(num);
     cout <<ans <<endl;
     return 0;
}

输出如下:

2

竞争编程的位技巧

如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请发表评论。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: