03-1 算法推送--二進位

2021-03-01 零點酒肆
13

這周是本學期上課周倒數第三周啦,為了讓同學們面對程設作業和考試時更加從容,本期我們將介紹兩套使用較廣的工具:位運算STL庫

位運算

本來以為同學們對位運算完全不了解,結果隨機採訪了幾位同學:

根據我們樣本數高達 的大數據調查(霧):

因此我們普及位運算變得十分必要(大霧

基本定義

為了方便後面的實例運用,還是先回顧一下簡單的定義

與(&)、或(|)、非(~)在c++中並不一定需要用到符號,也可以使用關鍵字(c++11標準)進行相應的運算按位與(&):可用 bitand(一定不要只寫 and,這是邏輯與的意思)按位或(|):可用 bitor(一定不要只寫 or,這是邏輯或的意思)小編暫時不清楚取反運算符有什麼關鍵字代替,歡迎大家在後臺留言

當然是否使用關鍵字代替符號是大家的自由,但是其中的關鍵字能幫助我們理解這個運算,以按位與為例bitand=bit+and:

按位或和取反類似,但值得注意的是,當我們進行位運算的對象是 int 類型或者 short 類型等前面沒有加 unsigned 前綴的類型時,計算機儲存時會留出最高的二進位位用於儲存符號。

如 int 是 位有符號整數,其第 位上的 表示的是其正負性:

更具體的,大家可以自行搜索學習「補碼」,了解整數的符號儲存,這裡不加以展開為了方便,建議同學們在使用位運算時使用 unsigned 系列類型,以防止符號影響結果(或者儘量減少對負數的位運算)異或(^)講道理這個運算其實和前三者沒啥兩樣的,它有其簡潔的關鍵字 xor學過離散數學的同學就知道,這個運算可以由前面三個操作表示出來左移(<<)、右移(>>)

將二進位位向左/右平移若干位……

值得注意的是,由於儲存是有限的,故我們還需要考慮溢出的問題,這時,我們定義:

如,對於 位無符號整數 ,執行 x<<3 時,得到的結果是 01010000:

其中, 的最高三位直接被捨棄,剩下 位向高位平移 位,並在末尾補上

以上運算都有對應算符 &=,^=,<<=等……

奇妙應用

雖然有些人會說,你這位運算也沒用。我說我這有用,這是底層運算,四兩撥千斤。兩百多行的if語句,都扳不過我的幾個位運算……

1. 計算

眾所周知,在不考慮符號和溢出截斷時,當位置的每一位向左移動 位時,相當於其表示的數值乘上了

相應的,x >>= k 相當於將 x 整除了 (注意這裡的截斷表明了只能是整除)

而由於底層實現原因,位運算的速度比加減乘除運算快了不少 (當然這並不能成為你程序寫得醜的理由)

一般情況下,同級數字進行各類運算的運行時間有:位運算<加減<乘法<除法(經驗之談)2. 交換函數

平時大家使用的交換函數大多是藉助臨時變量進行交換:

int c = a;
a = b;
b = c;

但實際上,我們利用位運算可以避免創建新變量:

a ^= b;
b ^= a;
a ^= b;

具體的原理大家可以自行思索qwq

哦對,講實話,其實不用位運算也是可以避免創建新變量的orz

當然,這講實話只是一個稍顯「炫技」的技巧,平時臨時變量還是挺香的(感覺位運算非常適合出各種作業題,比如 「如何利用位運算快速取出變量低位連續的 」)

有興趣的同學可以自行取用:http://graphics.stanford.edu/~seander/bithacks.html#OperationCounting

3. 狀態壓縮

講實話這才是我寫這篇推送的原因qwq

五個同學過一條河,河中只有一條船,並且船上一次最多只能乘兩個人。A,B,C,D,E同學過河分別需要1,3,6,8,12分鐘,過河的速度由過河最慢者決定。要求這五位同學必須在30分鐘內全部渡河,問他們如何過河?(徐老師第十三次作業第二題)

在這道題中,使用狀態壓縮能非常方便地儲存搜索狀態:(五個人分別在河的哪一岸,船的位置)

相信大多數同學第一想法是直接保存 個元素(五個元素對應五個人的位置+一個元素保存船的位置)

void dfs(int A, int B, ..., int boat, int time)

或是運用指針引用數組

void dfs(int *position)

雖然這題的工作量並不大,但懶癌晚期患者的第一想法仍然是狀態壓縮——只需保存一個 int 值即可

具體的做法是,由於每一個人的狀態只可能在左岸(記為0)或是右岸(記為1),每一個人其實只需要一個bit位即可,那麼可以只記錄一個數字

的二進位最低位即為 的狀態,可使用 x&1 提取出來 的低位第二位為 的狀態,可使用 x&2 提取出來-記得提取出來的是 ,使用 (x>>1)&1 即可提取出 的低位第三位為 的狀態,可使用 (x>>2)&1 提取出來

那麼函數引用就變得非常簡單:

void dfs(int S)

同時,當第 名同學渡河時(可能從 變成 ,也可能 變成 ),狀態改變實現變得非常簡單:S^(1<<i)

兩位同學一起渡河也很簡單:S^(1<<i)^(1<<j)

由於作業還未結束,故這裡不放完整的代碼實現了(如有需要可以在公眾號後臺諮詢)

一個 西洋棋棋盤,在上面放置 個皇后,使它們互不攻擊,問有多少種擺放方式( 皇后問題)

這種問題一般使用搜索解決,但在搜索過程中,皇后的斜向攻擊佔位方式非常適合位運算中的移位運算,所以就有了這道題的不用數組版本(獻醜貼上自己的代碼qwq):

int Search(const int n, int s, int ld, int rd, int col) {
    if (s > n) return 1;
    int res = 0;
    for (int i = 1; i < (1<<n); i <<= 1) {
        if (i & (col | ld | rd)) continue;
        res += Search(n, s+1, (ld|i) << 1, (rd|i) >> 1, col|i);
    }
    return res;
}
 
int main() {
    int n;
    std::cin >> n;
    std::cout << Search(n, 1, 0, 0, 0);
    return 0;
}

當然,拿位運算來做這種簡單的事情有點委屈它老人家,這種將狀態壓縮至一個整數裡的方法有其更大功效,在動態規劃中廣泛使用(有興趣的同學可以自行搜索「狀壓dp」) 在魔方大作業中也有作用

當然位運算還有一大堆奇葩應用,這裡只是選取的一些同學們程設考試中可以使用到的一部分內容。

當然如果有其他需求歡迎留言,可能被我們選定為後期推送的主題!

相關焦點

  • 二進位上的明文算法
    接下來三天去桂州玩,所以這周就記錄一篇明文算法吧。零、背景上周起開始看書:經濟學、文學、歷史。是的,沒有看技術書。最近也在梳理自己的知識圖譜,看到了以前記錄的base64算法,這篇文章就來聊聊base64的本質吧。一、二進位的缺點所謂二進位可以理解為數據進行了加密或壓縮後的一種表示。加密和壓縮的好處大家根據自己的理解,可以想到對應的優點與缺點。
  • 十進位轉二進位的最新簡單算法
    上周末,給孩子輔導奧數的時候,發現居然有一道二進位題,題目是求兩個二進位的和。我的視頻課第一課中就介紹了二進位的特點「逢二進一,借一當二」,給孩子講了下,他還是順利的做了出來。然後,我又給孩子講了下十進位與二進位的轉換。
  • 基於RFID的二進位防碰撞算法的改進
    2 傳統二進位算法   2.1 傳統二進位算法的基本原理   在二進位搜索算法中,要能夠檢測出多張卡的存在,卡片的返回數據必須具有唯一性,且卡片在傳輸其UID(Ubiquitous Identifications,身份識別標籤)時必須準確、快速、同步,這是防碰撞檢測的關鍵。
  • 經典算法題:懂二進位(小米筆試題)
    來自:2015小米暑期實習筆試題題目:世界上有10種人,一種懂二進位那麼你知道兩個int32整數m和n的二進位表達,有多少個位(bit)不同麼? 備註:1、不定期將從留言區選出認真答題的1名朋友,贈與書籍《算法詳解(卷1)》一本(兌獎方法跟獲獎者私下溝通)請留言,說出你的解題思路。不定期整理相關的問題答案分享。
  • 51單片機整數二一十進位轉換的快速算法
    提出的快速算法思路是,首先求出整數中包含的1000的個數,方法是採用二進位整數的高6位作為其預估,再通過2次校正得到準確值。算法的關鍵是充分利用89C51單片機的兩條特殊指令――單字節乘和單字節除。其耗費時間不及使用sprintf()函數的1/10。
  • 基於二進位搜索的RFID標籤防碰撞算法研究
    1 RFID技術簡介  1.1 基本概念  RFID技術是一種非接觸的自動識別技術,其基本原理是利用無線射頻信號的空間耦合(電磁感應或電磁傳播)的傳輸特性,實現對被識別對象的自動識別。  RFID系統一般由兩個部分組成,即電子標籤和閱讀器。
  • Cortex―M0單片機二-十進位整數轉換的快速算法
    關鍵詞:Cortex-M0;單片機;二-十進位轉換BCD碼;常數除法;快速算法引言 在單片機應用系統中,一般都需要高效快速地完成系統所需要的任務,並在任務完成後使系統進入睡眠或低功耗狀態,以便最大限度地節省系統功耗,增強系統的抗幹擾能力
  • Cortex—M0單片機二-十進位整數轉換的快速算法
    許多單片機應用系統中都需要進行二進位整數轉換為十進位BCD碼的操作,以便實現系統信息的顯示。對於Cortex—M0系列單片機,由於其指令系統中沒有十進位調整指令和除法指令,使得一些文獻中提供的高效算法和技巧不再適用於這類單片機,從而造成上述轉換操作成為影響系統性能的重要因素,因此提高上述數制轉換速度對於提高系統運行效率有極大的促進作用。
  • 吳國平:除了十進位, 人類文明史上還有哪些進位算法?
    當我們看到像1、25、356……這些耳熟能詳的數字,大家都知道這是學習數學的基礎,代表全世界通用的十進位,即滿十進一,滿二十進二,以此類推。世界通用的十進位,對於現代文明的我們看來是那麼地熟悉自然。在人類文明進程過程中,算法並不是就只有十進位一種,在很多文明體系中出現各種各樣的算法,如二進位、二十進位等等。
  • 03-2 算法推送--STL
    深度懷疑這是本學期對大家最有用的一次推送(大霧相信大家總是能發現這麼一個怪象:同樣的程設作業,有同學在發下來不到一個小時就開始在群裡問第五題的題意了,而有的同學寫了幾個小時、又調了幾個小時…依然沒法通過……
  • 【二進位】----十進位數轉換成二進位數
    除了我們常見的十進位的數,還有二進位、五進位、八進位、十六進位和六十進位的數。今天我們來說說二進位。二進位是由0和1兩個數字來表示的數,它的基數是2,進位規則是「逢二進一」,借位規則是「借一當二」,是由18世紀德國數理哲學大師萊布尼茲發現的。
  • 600年前的二進位算法 比萊布尼茨早300年
    人們普遍認為,二進位算法是德國數學家格特弗裡德·萊布尼茨在18世紀初發明的。據《科學美國人》網站12月16日報導,一項研究顯示,法屬玻里尼西亞的曼格雷哇島上的居民使用二進位運算系統比萊布尼茨早了300年。
  • 十進位與二進位、八進位、十六進位互轉
    十進位與二進位互轉  首先理解十進位如何轉二進位:將十進位數據除以2直到商為0,然後將餘數從下往上排序連接,即可得到該數字的二進位數。如:整數1313/2=6餘16/2=3餘03/2=1餘11/2=0餘1取13餘數,倒序連接。
  • 騰訊實驗室使用AI 算法解決二進位安全問題
    圖文無關;圖片來源:攝圖網數據算法騰訊安全科恩實驗室使用 AI 算法解決二進位安全問題的一項研究被 NeurIPS 2020 接收,該研究首次提出了基於 AI 的二進位代碼 / 原始碼端到端匹配算法,與傳統算法相比效果非常出色,準確率大幅提升。
  • 二進位轉BCD(大四加三算法1)
    首先,看一下下面這張表格,把二進位(8』hFF)轉換為BCD(12』h255)的步驟列表。把二進位(8』hFF)轉換為BCD(12』h255)步驟列表(一張表說透徹)什麼是二進位轉BCD?有什麼用?4位二進位是16進位數,而生活中常用的數制是10進位數。怎麼樣用計算機來理解、表達生活中的10進位數?
  • AI 算法解決二進位安全問題,騰訊安全NeurIPS 2020論文有新方法
    機器之心發布 機器之心編輯部 騰訊安全科恩實驗室使用 AI 算法解決二進位安全問題的一項研究被 NeurIPS 2020 接收,該研究首次提出了基於 AI 的二進位代碼 / 原始碼端到端匹配算法,與傳統算法相比效果非常出色
  • 細思細恐,人生就像是二進位,不是0就是1
    在現代生活裡,在你不經意中,0和1幾乎無處不在。在你收看電視節目、聽著音樂、拍攝照片或使用計算機時,都有無數的0和1在忙碌著;在超市各種商品包裝上、在圖書上的條形碼裡,0和1更是無處不在。0和1的強大功能和神奇特性使二進位技術功能得以實現。有了二進位,0和1成為一切數的源泉,它們可以包容一切數,其他數可以被它們取代,它們也可以轉化為任何數,它們的這一功能任何數都取代不了。
  • 如何在Python中進行二進位搜索?搜索算法,中級python技術點
    為了使二進位搜索繼續工作,您需要保持正確的排序順序。這可以通過該bisect模塊來完成,您將在接下來的部分中閱讀該模塊。文章中,您將看到如何在Python中實現二進位搜索算法。現在,讓我們面對IMDb數據集。請注意,搜索的人與以前不同。這是因為必須對數據集進行排序以進行二進位搜索,從而對元素進行重新排序。
  • 二進位中 1 的個數(劍指 Offer 題解Java版)
    二進位中 1 的個數題目連結題目描述思路一. 利用Integer類的bitCount()二.二進位中 1 的個數題目連結NowCoder題目描述任意給定一個32位無符號整數n,求n的二進位表示中1的個數,比如n = 5(0101)時,返回2,n = 15(1111)時,返回4這也是一道比較經典的題目了
  • 破局傳統算法痛點,騰訊安全首提基於跨模態檢索的二進位代碼-源...
    Function-Level Binary Source Code Matching》,憑藉首次提出基於AI的二進位代碼/原始碼端到端匹配算法的創新研究入選。該論文首次提出了基於AI的二進位代碼/原始碼端到端匹配算法,與傳統算法相比,準確率大幅提升,並為逆向分析領域提供了新的思路,可提升工業部署方面的效率。目前,該論文成果已在騰訊安全科恩實驗室研發的代碼檢索工具BinaryAI實現了落地應用。