contributed by < yutingshih
>
目前尚未在實體機器執行 GNU/Linux,因此暫時在 Apple M1 Mac 上使用 Lima VM,參考 Lima VM with a foreign architecture (slow mode)
根據題目描述:
next_pow2
可針對給定無號 64 位元數值 x,找出最接近且大於等於 2 的冪的值,例如:
next_pow2(7)
= 8next_pow2(13)
= 16next_pow2(42)
= 64
其中「找出最接近且大於等於 2 的冪的值」指的應該是從所有大於等於 x
而且屬於 2 的非負整數次冪的數值當中選出最小值,即
因此當 x
剛好等於 2 的非負整數次冪時,next_pow(x)
應該要剛好等於 x
,例如:
next_pow2(1)
= 1next_pow2(2)
= 2next_pow2(4)
= 4這個結果剛好與題目給的範例程式輸出吻合
依照題目的指示,完成以下 next_pow2
的改寫
其想法為將 x
最高位的 set bit (值為 1
的位元) 以下的所有位元都設為 1
,再將結果 +1,即獲得一個最接近的 2 的冪,等同於
但對於 x
原本就是 2 的冪的狀況,以上實作顯然無法給出正確答案,例如當 x
等於 16 時:
x |
|
---|---|
initial | 00...001000 (16) |
after left shift | 00...001111 (31) |
after add 1 | 00...010000 (32) |
因此我們需要對以上實作做一些修改,我們觀察一下給定不同 x
值時 next_pow2
計算結果的規律
x |
next_pow2(x) 計算結果 |
next_pow2(x) 正確答案 |
---|---|---|
… | ||
我們可以發現當 x
為 2 的冪時,輸出會是正確答案的 2 倍,同時我們發現如果把 x
減 1 後再做位元運算即可滿足正確答案
x |
next_pow2(x-1) 計算結果 |
next_pow2(x) 正確答案 |
---|---|---|
… | ||
但這個做法 (左移運算之前先減 1) 在 x
為 0 時仍會出錯,根據題目要求 next_pow2(0)
應該要得到 1,但當我們對 0 進行減法卻會導致溢位發生,最後算出來結果是 0,如同以下過程
x |
|
---|---|
initial | 00...000000 (0) |
after left shift | 11...111111 (UINT64_MAX) |
after add 1 | 00...000000 (0) |
因此我們需要特別處理 x
為 0 的狀況,當 x > 0
時,先減 1 再做位元運算,當 x == 0
時,直接做位元運算 (也可以說減 0 後再做位元運算),因此我們只需要添加下面這一行即可
將 x % (1e9 + 7)
運算改用 bitwise operator,得先將 使用二進位來表示