C语言中的 &,^ ,| , ~ , >>,<< 六个运算符与lowbit函数

首先我们为了更好的了解这些位运算的运算过程和原理,我们得先明白进制之间的转化。

首先我们得知道十进制与二进制之间的转化。

进制转化:

在这里举两个例子

183:1 0 1 1 0 1 1 1

98:1 1 0 0 0 1 0

转化代码:

 int a[10000];
    int t = 183;//98
    int cnt = 0;
    while (t)//有两种方法,任选一种即可
    {
       /* if (t & 1)//t为奇,相当于t%2==1
        {
            a[cnt++] = 1;
        }
        else
        {
            a[cnt++] = 0;
        }
        t /= 2;*/
        a[cnt++] = t % 2;
        t /= 2;
    }
    reverse(a, a + cnt);//倒置数组。

将一串二进制转化为十进制数字,如下:

(从右往左的以2为底,各数字对应的位权次方(0开始)乘以该数组位置上的数,其总和即为十进制最终得数)

  int sum = 0;
    int o = 0;
    for (int i = cnt-1;i>=0;i--)
    {
        sum += pow(2, o++) * a[i];
    }
    cout << sum << endl;

&(按位与)运算 AND:

&:相同则同,否则0。

183:1 0 1 1 0 1 1 1

98: 1 1 0 0 0 1 0

183&98=34。

34: 1 0 0 0 1 0

由按位运算规则可以知道,任何数&1,不是0就是1。所以我们可以通过这一点来判断一个数的奇偶性。用 (x&1) 来代替 (x%2==1)。

^(按位异或)运算 XOR:

^:相同为0,不同为1

183:1 0 1 1 0 1 1 1

98: 1 1 0 0 0 1 0

183^98=213。

213: 1 1 0 1 0 1 0 1

由上述可知,任何二进制数与零异或,都会等于其本身,即 A ^ 0 = A。

异或性质

(1)交换律: A ^ B = B ^ A

(2)结合律: ( A ^ B ) ^ C = A ^ ( B ^ C )

(3)自反性: A ^ B ^ B = A (由结合律可推: A ^ B ^ B = A ^ ( B ^ B ) = A ^ 0 = A)

这里我们就多出一种交换两个数而不使用中间变量的方法:

a = a ^ b; // a = 3 ^ 7

b = a ^ b; // b = (3 ^ 7) ^ 7 = 3 ^ (7 ^ 7) = 3

a = a ^ b; // a = (3 ^ 7) ^ (3 ^ 7 ^ 7) = (3 ^ 3) ^ (7 ^ 7) ^ 7 = 7

|(按位或) OR:

|:有1则1。无则0;

183:1 0 1 1 0 1 1 1

98: 1 1 0 0 0 1 0

183|98=247。

247: 1 1 1 1 0 1 1 1

~(取反):

183:1 0 1 1 0 1 1 1

~183: 0 1 0 0 1 0 0 0

>>(右移):

183:1 0 1 1 0 1 1 1

其功能是把“>> ”左边的运算数的各二进位全部右移若干位, “>>”右边的数指定移动的位数。

右移相当于该数除以2的n次方,前提是数据不能丢失。

183>>2:0 0 1 0 1 1 0 1 =45。

<<(左移):

183:1 0 1 1 0 1 1 1

其功能是把“>> ”左边的运算数的各二进位全部右移若干位, “>>”右边的数指定移动的位数。

左移相当于该数乘以2的n次方,前提是数据不能丢失。

183<<2:1 0 1 1 0 1 1 1 0 0 = 732

lowbit函数:

之前在cf上遇到过一个题目:Problem - C - Codeforces

问到一个数n & (n+1) & … & m=x,需要按位到多少才能等于x,当然,这个x一定会比n小

其中学到了一个lowbit函数:

用来取一个二进制最低位的一与后边的0组成的数

比如:5(101),lowbit(5)=1(1)

12(1100),lowbit(12)=4(100)

在这里换言之其中的作用是返回刚好能够改变二进制最后一个1(使之变为0)的十进制整数。

ll lowbit(ll x)
{
    return x & (-x);//x&(~x+1)
}

其中(-x)=(~x+1)其实就是x+~x=-1的前身,换个位置就好了。

#include<math.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<map>
#include<list>
#include<string>
#include<queue>
#include<set>
#include<vector>
#include<stack>
#include<limits>
#define re register
#define iosgo() std::ios::sync_with_stdio(false),std::cin.tie(nullptr),std::cout.tie(nullptr);
#define run(i,n) for (int i = 1; i <= n; i++)
#define cin std::cin
#define cout std::cout
#define ll long long
#define endl "\n"
using namespace std; 
typedef pair<int, int>pll;
inline ll read()
{
    ll x = 0, w = 1; char ch = getchar();
    for (; ch > '9' || ch < '0'; ch = getchar())if (ch == '_')w = -1;
    for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    return x * w;
}
ll lowbit(ll x)
{
    return x & (-x);//x&(~x+1)
}
void solve()
{
    ll n, x;
    n = read(); x = read();
    if (x > n)
    {
        cout << "-1\n"; return;
    }
    if (n == x)
    {
        cout << n << endl; return;
    }
    while (n >= x)
    {
        ll temp;
        temp = n + lowbit(n);
        n &= temp;
        if (n == x)
        {
            cout << temp << endl;
            return;
        }
    }
    cout << "-1\n";
}
int main()
{
    int t;
    t = read();
    while (t--)
    {
        solve();
    }
}

猜你喜欢

转载自blog.csdn.net/YZcheng_plus/article/details/128780784
今日推荐