1.二进制最高位称为“符号位”。1表示该数为负值,0表示为正值
2.正数的原码,反码和补码是一样的
3.负数的反码为符号位不变其他位取相反
负数的补码为 反码+1
运算符
& 按位与
| 按位或
^ 按位异或
~ 取反
<< 左移 >> 右移
比如,6的二进制是110,
—1 1 0
(取反)0 0 1+1 = 0 1 0
按位与运算 得到 0 1 0
0 * 22+1 * 21+0*20 =2
所以lowbit(6)=2。
找出落单的筷子的长度
#include<iostream>
using namespace std;
int main()
{
int n;
int a,b;
a=0;
cin>>n;
while(n--){
cin>>b;
a^=b; //0^m^m^n=n;相同的数进行按位异或为0
}
cout<<a<<endl;
return 0;
}
二进制表示中最右边是第0位
位运算两个最常用的操作
一.n的二进制表示中第k位是几
1.先把第k位移到0位 m=n>>k;
2.看个位(0位)是几 x=m&1; 就将数取出来了
将两者结合起来就是 x=n>>k&1;
10二进制位(1010)
10>>3&1; 为1(最左边的);
3表示第3位移到0位
二.lowbit(x)是树状数组的基本操作
lowbit(x)返回的是最后一位1,(从右往左数)
可以用来求一个数二进制中1的个数
#include<iostream>
using namespace std;
int lowbit(int x)
{
return x&-x;
}
int main()
{
int n;
cin>>n;
while(n--){
int x;
cin>>x;
int ans=0;
while(x) x-=lowbit(x),ans++; //x-=lowbit(x); 每一次减去一个1
cout<<ans<<" ";
}
return 0;
}
二进制x=101000,lowbit(x)=1000;
int lowbit(int x)
{
return x&(-x);
}
B. Rock and Lever
https://codeforces.com/contest/1420/problem/B
//注意数据范围,因为这玩意wa了几次
/*
这道题暴力没有过,只能找规律
因为& 与 ^ 我们寻找1最后出现的位数,并且有几次
*/
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
long long sz[N];
long long num,sum,x,mx;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
long long a[n+1];
x=0;
mx=0;
memset(sz,0,sizeof sz);
for(int i=1;i<=n;i++)
{
cin>>a[i];
x=a[i];
num=0;
while(x)
{
num++;
x/=2;
}
sz[num]++;
mx=max(mx,num);
}
sum=0;
for(int i=0;i<=mx;i++)
{
sum+=sz[i]*(sz[i]-1)/2;
}
cout<<sum;
if(t!=0) cout<<endl;
}
return 0;
}