0x表示十六进制
算数位运算(不仅可以进行逻辑运算,还可以进行算数运算
与 :‘&’ //两个数都为1则为真
或:‘|’ //两个数只要有一个为 1 则真
非:‘~(!)’ //数为0,则位真;数为1,则为假
异或:‘^’ //两个数不相等则为真
二进制就将两数每一位从左往右分别计算
反码
跟原码是正数时,一样;负数时,反码就是原码符号位除外,其他位按位取反。
补码
二进制最高位的数为1则为负数,为0则为非负数
对于最高位为0的每种编码c,直接看作32位2进制数s
则c按位取反得到的~c表示的数值为-1-s
1=0000000000...01(共32位,下同)
2=0000000000...10
3=0000000000...11
1+1111111111...11=0000000000...00
2+1111111111...10=0000000000...00
x+?=0000000000...00
所以?=~x+1
-x=~x+1
移位运算
左移
1->10->100(将1向左移n位 1<<n=2^n
n<<1=2n
右移
n>>x=n/2^x算数右移高位以符号码补充,低位越位舍去;逻辑右移高位以0补充,低位越位舍去
a^b
/*首先a^b,a^b中可以设b=2^t1+2^t2+…+2^tk(二进制) 即将b转换为二进制表示
b&1就是判断b的二进制表示中第0位上的数是否为1,若为1,b&1=true,反之b&1=false */
#include<iostream>
using namespace std;
int main(){
long long a,b,p;
cin>>a>>b>>p;
long long res=1%p;
while(b){
if(b&1) res=res*a%p;//b&1求出b二进制最低位
a=a*a%p;//准备好十位
b>>=1;//去除个位
}
cout<<res;
return 0;
}
二进制中一的个数
思路:
(lowbit) O(nlogn)O(nlogn)
使用lowbit操作,进行,每次lowbit操作截取一个数字最后一个1后面的所有位,每次减去lowbit得到的数字,直到数字减到0,就得到了最终1的个数,
lowbit原理
根据计算机负数表示的特点,如一个数字原码是10001000,他的负数表示形势是补码,就是反码+1,反码是01110111,加一则是01111000,二者按位与得到了1000,就是我们想要的lowbit操作
#include<bits/stdc++.h>
using namespace std;
int lowbit(int x){
return x&-x;//逻辑运算符
}
int cnt;
int main(){
int n;
cin>>n;
while(n--)
{
cnt=0;
int x;
cin>>x;
while(x) x-=lowbit(x),cnt++;
cout<<cnt<<" ";
}
return 0;
}
64位整数乘法
(二进制思想) O(logn)O(logn)
如果直接计算a乘b这会超过 long long 的最大范围,所以采用类似于快速幂的思想
把 b写成二进制形式,然后如果某位上为1就加上它a*(2^n)次方(n与这位的位置有关)
并且每次计算后取模就可以了
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int main(){
ull a,b,p;
ull asn=0;
cin>>a>>b>>p;
while(b){
if(b&1)asn=(asn+a)%p;
b>>=1;
a=a*2%p;
}
cout<<asn<<endl;
return 0;
}