目录
-
- 位运算
-
- 应用
位运算
要明白位运算是在二进制中的运算方式,所有其他进制的数在进行位运算时都要先转化成二进制数再进行运算。
int 是 32位二进制。有符号整型 :正数:0 负数:1
1:00000....0001
-1:10000.....0001
1.按位与(&)
只有当x,y都是1的时候,运算结果才是1,其余情况都是0.
1&1=1 1&0=0;
例如5 & -5
5 : 0000 0000 0101
-5 :1111 1111 1011
答案 : 0000 0000 0001
2.按位或(|)
x,y中只要有一个是1,结果就是1,其余情况为0.
1|1=1 ,1|0=1;
例如5 & -5
5 : 0000 0000 0101
-5 :1111 1111 1011
答案 :1111 1111 1111
3.按位非(!)
!x 如果x为0,!x=1 ; x=1的话!x=0.
5
0000 0000 0101
答案:1111 1111 1010
4.按位异或(^)
x^y 相同是0,不同是1,
1^1=0 , 1^0=1 , 0^0=0 ;
5 ^ -5
0000 0000 0101
1111 1111 1011
答案: 1111 1111 1110
5.反码(~)
按位取反
5 : 0000 0000 0101
~5 : 1111 1111 1010
6.补码
(1)如果为正数:正数的补码就等于原码;
(2)如果为负数:负数的补码就是在该数字的反码上+1;(-x的补码=~x+1)
-5的补码
5的二进制数 : 0000 0000 0101
5的反码: 1111 1111 1010
最后再加1 : 1111 1111 1011
-5的补码为: 1111 1111 1011
7.左移 右移
将一个数二进制下的数向左(向右)移若干位,
比如 x << y 就是将二进制下的x 向左移 y 位.
比如 x >> y 就是将二进制下的x向右移y位。
1<<x 01 10 100 1 2 4 左移就是扩大2的倍数
4>>x 100 10 01 4 2 1 右移就相当于除以2
其中除了取反( ~ )以外,其他的都是二目运算符,即要求运算符左右两侧均有一个运算量。
应用
1.a^b;
求 a 的 b 次方对 p 取模的值。
输入格式:
三个整数 a,b,p ,在同一行用空格隔开。
输出格式:
输出一个整数,表示a^b mod p的值。
数据范围
0≤a,b,p≤109
数据保证 p≠0
输入样例:
3 2 7
输出样例:
2
代码
#include<iostream>
using namespace std;
int main()
{
int a,b,p;//a=3,b=2,p=7;
cin>>a>>b>>p;
int res=1%p;
while(b)//2的二进制为10
{
if(b&1) res=res*1ll*a%p;//第一次个位为0,a=(3*3)%7;
a=a*1ll*a%p;//1ll 1的long long 形式
b>>= 1;//第一次右移后个位为1,res=(1*3*3)%7=2
cout<<res<<endl;
return 0;
}
2.64位整数乘法
求 a 乘 b 对 p 取模的值。
输入格式
第一行输入整数a,第二行输入整数b,第三行输入整数p。
输出格式
输出一个整数,表示a*b mod p的值。
数据范围
1≤a,b,p≤1018
输入样例:
3
4
5
输出样例:
2
代码
#include<iostream>
using namespace std;
int main()
{
long long a,b,p;//a=3,b=4,p=5;
cin>>a>>b>>p;
long long res=0;
while(b)//4的二进制位100
{
if(b&1) res=(res+a)%p;//第一次个位为0 res=0 a为3*2
a=a*2%p;
b>>=1;//第一次右移后个位为0,res=0 a为3*2*2 ;第二次右移后个位为1,res=(0+3*2*2)%5=2
}
cout<<res<<endl;
return 0;
}