contributed by < Chao-Shun-Cheng
>
1
首先可以觀察 a >> 1
與 b >> 1
是直接先進行除以 2 的動作再相加,不過要去補償是不是第一個 bit
都是 1,如果是的話要補償回來。
Example
a
= 0101, b
= 0011, (a + b) / 2
= 0100
a >> 1
= 0010, b >> 1
= 0001, (a >> 1) + (b >> 1)
= 0011
(a >> 1) + (b >> 1) + (a & b & 1)
= 0100
所以 EXP1
是 a & b & 1
。
可以觀察到兩數相加可以分為要進位的 bit
跟不須進位的 bit
,假如是要進位的 bit
再除以 2 其實就是自己本身,而不需要進位的 bit
則需要另外再除以 2。因此可以知道 EXP2
是代表要進位的 bit
,所以 EXP2
是 a & b
;EXP3
則是代表不須進位的 bit
,所以 EXP3
是 a ^ b
。
2
假設 a > b
那就代表 a ^ ((EXP4) & -(EXP5)) == a
,另外我們知道 a ^ 0 = a
,所以代表當 a > b
時 (EXP4) & -(EXP5) == 0
。再來 EXP5
是 logical operator,只會輸出 0
或 1
再加上負號,所以會只有 0
跟 -1
兩種可能性。因此我們可以推出 EXP5
就是 a < b
。另外我們知道 a ^ a = 0
,因此我們可以推出 EXP4
就是 a ^ b
。
3
首先可以看到第六行的 for
迴圈,會利用 shift
把最大公因數裡有幾次 2 存起來。再來 do while
做的事情就跟 GDB 說明程式一樣,因此 COND
就是 v
。當結束 while
迴圈,就代表 u
是最大公因數,但還要記得用 shift
補償回去,因此 RET
就是 u << shift
。
4
第八行開始的 while
迴圈就是直接利用 __builtin_ctzll
去找出有 1 的位置,再存進去 out
裡面,其中 t
用來存從低位元開始,第一個出現 1 的位置。
Example
a
= 1010, -a
= 0110
a & -a
= 0010
因此 EXP6
就是 bitset & -bitset
5
這題主要是建立 1024 個大小的 hash table
來去尋找是否有相同的餘數。首先看到第 7 與 12 行,先確定除數跟被除數都非 0 。35 行則是先將整數的部分存進 result
裡面,緊接著就是進入 for
迴圈處理餘數的部分。可以先看到 66 行會建立 node
,並把餘數當作是 key
,要存進去 hash table
裡面。第 70 行就是要將 node
存進對應的 bucket
裡面,因此 MMM
就是 list_add
,而 EEE
就是 heads + (remainder % size)
。第 72 行則是把看目前的數字存進 decimal 裡面。緊接著回頭看第 55 行,如果有找到對應的值,就代表發生循環小數,不過循環小數不一定是小數點第一位,因此要先將循環小數前面的數字存進 result
裡面,因此可以得知 PPP
就是 pos--
。
6
從題目可以知道會回傳 alignment
的大小,因此只要我們知道一個 member 所佔的大小即可知道答案。因此可以知道 M
就是 _h
,而 X
就是 0
7
7
先從以下程式碼可以知道, length 會代表要 print 出來的長度,因此可以知道當整除三同時整除五時 length = 8
,當只有整除五或只整除三時 length = 4
。因此可以猜出 KK1
就是 div3
,KK2
就是 div5
。
再來看 17 行的程式碼,會有以下幾種情況可以觀察
(9 >> div5) >> (KK3) = 0
9 >> KK3 = 0
(9 >> div5) >> (KK3) = 4
9 >> 1 = 4
代表 KK3 = 0
(9 >> div5) >> (KK3) = 9
KK3 = 0
(9 >> div5) >> (KK3) = 0
9 >> 1 = 4
代表 KK3 >= 3
因此可以推斷出 KK3
就是 div3 << 2