位運算**好…
在這裡,我拿洛谷p2104的題當作例題
題目:
小z最近學會了二進位制數,他覺得太小的二進位制數太沒意思,於是他想對乙個巨大二進位制數做以下 4 種基礎運算:ac**如下:運算 1:將整個二進位制數加 1
運算 2:將整個二進位制數減 1
運算 3:將整個二進位制數乘 2
運算 4:將整個二進位制數整除 2
小z很想知道運算後的結果,他只好向你求助。
(ps:為了簡化問題,資料保證+,-操作不會導致最高位的進製與退位)
輸入格式
第一行兩個正整數 n,m,表示原二進位制數的長度以及運算數。
接下來一行 n 個字元,分別為『0』或『1』表示這個二進位制數。
第三行 m 個字元,分別為『+』,『-』,『*』,『/』,對應運算 1,2,3,4。
輸出格式
一行若干個字元,表示經過運算後的二進位制數。
#include
#include
#include
using namespace std;
#define n 10000005
int s[n]
;int
main()
while
(m--
)else
}for
(int i=n;i>
0;i--
)for
(int i=
1;i<=n;i++
)printf
("%d"
,s[i]);
return0;
}
所實話,這道題玩了我一天,看答案看了許久,最後才知道怎麼做。
首先,我們要先了解什麼是位運算:
位運算基礎舉個栗子:&按位與
如果兩個相應的二進位制位都為1,則該位的結果值為1,否則為0
|按位或
兩個相應的二進位制位中只要有乙個為1,該位的結果值為1
^按位異或
若參加運算的兩個二進位制位值相同則為0,否則為1~取反
~是一元運算子,用來對乙個二進位制數按位取反,即將0變1,將1
<<
左移用來將乙個數的各二進位制位全部左移n位,右補0
/>>
右移將乙個數的各二進位制位右移n位,移到右端的低位被捨棄,對於無符號數, 高位補0
&:10001&10010=10000
|:10010|11100=11110
/>>:(前面的 / 忽略不計,這裡是因為不打 / 就打不出》 )
10010>>1=1001
<<:
1001<<1=10010
然而這些只是基本概念。下面聊聊我對》 << 的理解:
<< 是左移一位,因為計算機儲存資料是二進值儲存,所以將資料左移一位之後相當於整體擴大一倍,也就相當於ax2。
/>>是右移動一位,它的功能也就是除以2。以我們從小到大的經驗,難點,易錯點往往出再除法上。
對於負數字運算有乙個基礎點:無論是左移還是右移,這個數的符號位是不發生變化的,說簡單點,就是負數怎麼移還是負數,正數怎麼移也就只能是0或者正數。
如果大家有興趣的話可以在其他方看比較正統的負數右移的解釋。但在這裡我給乙個比較簡單的理解方式:
舉個栗子:
3/2=1.5 而 3>>1=1
2/2=1 而 2>>1=1
-1/2=-0.5 而 -1>>1=-1
-2/2=-1 而 -2>>1=-1
-3/2=-1.5 而 -3>>1=-2
看到這裡,相信聰明的你們已經發現規律了吧!
向右移以為就是除二取小有一點[1.5]=1 [-1.5]=-2的感覺。如果不知道 [ ] 是什麼意思,那我也木的辦法。
我講這麼多也就是解釋下這一步是幹什麼的:
for
(int i=n;i>
0;i--
)
至於這道題的題解,我覺得如果懂了負數的位運算,看我的**應該都能懂了,如果不懂的可以取題解裡看看大佬的發言(蒟蒻瑟瑟發抖 ) 負數的或運算
場景 有乙個函式的返回值是乙個狀態量,我希望用這個狀態量的每一位來表示一種狀態的t f。迫於強迫症,這個返回的值應該是負數的。所以一開始我大概是這樣寫的 if if yyy if zzz 但是這個結果一直是 1。原來以為負數的或運算和正數的或運算是一樣的,1 2 3這樣的。後來想了下,因為在計算機裡...
對位運算中問題的闡述
左移操作符 左邊拋棄 右邊補0 左移時邏輯移位和算術移位相同。右移操作符 邏輯移位 左邊用0填充 算術移位 左邊用原該值的符號位填充。c標準說 無符號數執行所有移位都是邏輯移位。但對於有符號的數移位,採用哪種移位方式是根據編譯器決定的。使用技巧 偽 呈現 求二進位制最低位 使用 二進位制數 1 的高...
有序集合間的對位運算
摘要 兩個有序集合之間可能進行一一對應的計算,比如兩個集合如何比較大小,怎樣判斷集合是否相等?如何簡便快捷的處理集合間的對位運算,這裡為你全程解析,並提供 esproc 示例 有序集合間的對位運算 有序集合間的對位運算,包括比較運算 等於 和四則運算 本問中討論的集合,都是有序集合,有序集合的成員是...