實用技巧之位運算

實用技巧

位運算
1(十進制)=01(二進制)

&

兩個二進制碼位置如果同時是1則結果爲1,其餘爲0
b&1
所以“&1”“%2”是判斷奇偶的,是奇數則爲1

>>

右移運算
1.二進制碼向右挪x個長度,右邊擠掉
2.可以取出二進制表示下的某一位,例如:n^(1<<k)表示二進制下第k位去取反。
b>>=1
“>>1”=除二
b>>x就可以取出b的二進制碼中的第x位
(x是一個數字)

b&1可以取出b在二進制表示下的最低位
b>>1可以捨去最低位

<<

左移運算
1<<b求2的b次方
常用long long len = 1 ll<<(n-1);
long long cnt = 1 ll<< (2*n-2);
注意類型轉換
1<<n
左移運算在圖中的應用就是標記遍歷的點,1表示這個位置沒有被走過,0表示已經走過,每運算一次,就左移一下

^

異或運算
兩個相同則爲0,否則爲一

1.兩個相同數異或的結果爲0
2.0異或任何數都爲那個數

應用:
在一組數中找出不同的數

例1:一個數組中,只有一個數出現了一次,請你找出這個數,其餘的都是2次
前綴和+異或
全部數異或後結果就是那個單次的數(有重複的都異或爲0了)

int n;
cin>>n;
int a[n+1];
a[0]=0;
for(int i=1;i<=n;i++){
    cin>>a[i];
    a[i]^=a[i-1];
}
cout<<a[n];

例2:
一個數組中有2個出現一次的數,請你求出這2數
分析
要想找出兩個單次的數,其實我們只需要將這個數組一分爲二,保證這兩部分各包含一個出現一次的數
目標轉換:
求如何分解數組
根據上題經驗,全部異或的結果肯定是那兩個單次數異或的結果
所以異或的結果中的二進制碼中肯定有1
而那個1就是這兩個單次出現的數的不同之處
於是我們記錄這個位置pos
所以我們可以依據數組中的數的pos位置有無1來將數組分爲兩大類
分完類,做法就與例1做法一樣了

提示:
我們可以使用“>>”來取出每個位置,並用&運算來判斷這個位置是否是1

int n;
cin>>n;
int a[n+1];
a[0]=0;
int num=0;
int a1=0,a2=0;
for(int i=1;i<=n;i++){
    cin>>a[i];
    num^=a[i];
}
int pos= 0 ;
for(int i=0;i<32;i++){
    if(((num>>i)&1) == 1){
        pos=i;
        break;
    }
}
for(int i=1;i<=n;i++){
    if(((a[i]>>pos)&1)==1){
        a1^=a[i];
    }else{
        a2^=a[i];
    }
}
cout<<a1<<" "<<a2;

|

或運算
例1給你一個數組,求將這個數組的每個數組合搭配後形成小數組,小數組的值按位或後,有多少種不同的結果
樣例:1 1 1 2

這篇寫完,我自己都提升了,難道不值得贊嗎???

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章