1. 补码
由于CPU在进行设计的时候只进行了加法器的设计,所以在它只会处理加法操作,那么问题来了如何进行减法操作呢?例如:A-B,我们可以将其看作是A+(-B)的形式。这样在计算机内部就会出现负数的形式,所以就引入了补码的概念,补码就是对数字进行按位取反再加一的操作,补码在计算机中进行储存负数。
2. 移位运算
1. 左移
就是将二进制中的bit位向左移动一位,低位用0进行填充,高位越界后舍弃。
2. 右移
1. 算数右移
就是将二进制中的bit位向右移动一位,高位用符号位进行填充,低位越界后舍弃。值得注意的一点-3>>1=-2, -3/2 = -1,算数右移按照向下取证的观点,除法运算按照向0取证的观点。
2. 逻辑右移
就是将二进制中的bit位向右移动一位,高位用0进行填充,低位越界后舍弃。
3. 二进制状态压缩
将一个长度为m的bool数组用二进制整数的每一bit位来表示并存储的方法。
常用操作:
1. 取出n的第k位bit的数值:n>>k & 1
2. 取出n的0-k位的数值:n & ((1 << k) -1)
3. 将n的第k位进行取反操作:n ^ (1 << k)
4. 将n的第k位赋值成1:n | (1 << k)
5. 将n的第k位赋值成0:n & (~(1<<k))
4. 成对交换
我们对n进行n^1的操作时发现,如果n为奇数这个操作可以转化成与他相邻的偶数,n ^ 1 ^ 1这样可以得到n本身,这样的数字交换称为成对交换。
5. lowbit运算
lowbit(n)表示非负数的最后一位1表示的数值是多少
inline int lowbit(int n){
return n & -n;
}
相关练习:
#include<iostream>
using namespace std;
int qmi(int a, int b, int p){
int t = 1;
while(b){
if(b&1) t = 1ll * t * a % p;
a = 1ll * a * a % p;
b >>= 1;
}
return t % p;
}
int main(){
int a,b,p;
cin>>a>>b>>p;
cout<<qmi(a,b,p)<<endl;
return 0;
}
#include<iostream>
using namespace std;
typedef long long LL;
LL a, b, p;
LL res(LL a, LL b, LL q){
LL ret = 0, t = 1;
while(b){
if(b & 1) ret = (ret + a) % q;
b >>= 1;
a = a * 2 % q;
}
return ret % q;
}
int main(){
cin>>a>>b>>p;
cout<<res(a,b,p)<<endl;
return 0;
}
#include<iostream>
using namespace std;
int T, H, M;
typedef long long LL;
LL sum;
void calc(int x, int y){
LL t = 1;
while(y){
if(y & 1) t = (t * x) % M;
x = 1ll * x * x % M;
y >>= 1;
}
sum = (sum + t) % M;
}
int main(){
cin>>T;
while(T--){
cin>>M>>H;
sum = 0;
for(int i = 0; i < H; ++i){
int l, r;
cin>>l>>r;
calc(l, r);
}
cout<<sum <<endl;
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
typedef pair<string, int> PSI;
const int N = 1e5+10, M = 1e9;
PSI op[N];
int n, m;
int calc(int bit, int num){
for(int i = 1; i <= n; ++i)
if(op[i].first == "AND") num &= op[i].second >> bit;
else if(op[i].first == "OR") num |= op[i].second >> bit;
else num ^= op[i].second >> bit;
return num & 1;
}
int main(){
#ifdef _DEBUG
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
cin>>n>>m;
for(int i = 1; i <= n; ++i)
cin>>op[i].first>>op[i].second;
int res = 0, ans = 0;
for(int i = 29; ~i; --i){
int l = calc(i, 0), r = calc(i, 1);
#ifdef _DEBUG
cout<<i<<' ' << l << ' '<<r<<endl;
#endif
if(res + (1 << i) <= m && l < r){
ans += r << i;
res += 1 << i;
}
else ans += l << i;
}
cout<<ans<<endl;
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1 << 20, M = 20;
int f[N][M], path[M][M];
int n;
int main(){
cin>>n;
for(int i = 0; i < n ;++i){
for(int j = 0; j < n; ++j){
cin>>path[i][j];
}
}
memset(f, 0x3f, sizeof f);
f[1][0] = 0;
for(int i = 1; i < (1 << n); ++i){
for(int j = 0; j < n; ++j){
if(i & (1 << j)){
for(int k = 0; k < n; ++k){
if(((i - (1 << j)) & (1 << k))){
f[i][j] = min(f[i][j], f[i - (1<<j)][k]+path[k][j]);
}
}
}
}
}
cout<<f[(1<<n)-1][n-1]<<endl;
return 0;
}