contributed by < shlin41
>
原理是將欲求平方根的 拆成:
進一步擴充:
則可以得到:
我們的目的是從試出所有 , or 。從 一路試到 ,而求得 只要試驗 是否成立。但是計算 成本太高,所以在這個基礎上,希望可以找另外一種比較方法。
先定義:
則可以得到:
再對 進行處理:
結合上述方法撰寫演算法來尋求 ,假設從 開始往下試。
因為是從 開始,所以:
int m
對應上述理論中的 ,由於首項 ,可知指數項是 2n,所以程式中的 & ~1UL
是為了取偶數
int m = 1UL << ((31 - __builtin_clz(x)) & ~1UL)
用 fls()
會相對容易,但是 C POSIX library 只有 ffs()
。因此直接借用 linux-kernel 原始碼中的 __fls()
。
查找過程中發現 __fls()
有分成硬體實做與軟體實做
取代部份
[TODO]
[TODO]
題目已經證明:假設我目標的最大數是 , 則是比 還要小的非負整數。假設 ( 是十位數 是個位數),且 ( 是十位數, 是個位數),則只要以 算出來的除數 ,在 後能保持在精確度內,則 除以該除數 仍然會在精確度內。
我們的目標 n = UINT_MAX = 4294967295
,一樣是要找出 ,並滿足下式
整段程式還看不懂:
(in | 1)
改成 (in)
的話,答案會在 20 的倍數的 in
出錯*mod = in - *dev * 10
q & ~0x7 = *div << 3 = *div * 8
[TODO]
[TODO]
答案的部份
整個程式的目標是找出最開頭的 bit = 1
的位置。作法是使用二分搜尋法。
解釋第一個 while:
輸入是一個 32 個位元的無號整數 i
,分成前 16 位元和後 16 位元。如果 ,則表示前 16 位元有 bit = 1
存在。所以 result += 16,並且把原數字 i >> 16
,繼續看前 16 位元。反之,如果 ,則表示前 16 位元都是 0。所以 result 保持不變,繼續看後 16 位元。
其他 while 比照處理。
[TODO]
概念上還是
差別在於存 internal 時,會把 後,再存入。讀取平均值時,會把 後,再讀出。
解析這一段:
上式可改寫為
至於為什麼要引入 factor,我尚未了解其目的。
[TODO]
答案的部份: GGGG = 1
程式的最後部份
等於
只是把 的 shift 部份補上。程式的概念上和測驗三是一樣的。
原程式在 ceil_ilog2(1) = 1
且 ceil_ilog2(0) = 32
為錯誤值。正確的ceil_ilog2(1) = 0
且 ceil_ilog2(0)
應該是沒有定義。因此在 x == 0
自行定義回傳值為 0。程式碼改進如下:
使用一個 mask
,在 x <= 1
時, mask = 0x00000000
,函式回傳 0。x > 1
時,mask = 0x0000003f
,函式回傳舊有的值。
mask = 0x0000003f
是因為函式回傳值最大為 。
[TODO]
答案的部份: AAAA = 1
運作原理已在題目講解清楚說明。
Time Complexity: O(n)
Space Complexity: O(1)
參考之前的作業 reference
1. 找 subtree 中的 max/minminmin
2. Rotation:調整樹高的基本操作
3. 計算樹高與平衡性:用來決定要不要調整的依據
4. 決定是否調整樹的架構:這個 function 可以快速 implement 成 AVL-Tree
AVL-Tree Implementation:
if (n->hint == 0 || n->hint != prev_hint)
xt_update(root, p);
把條件式刪除讓 root 到 node 間的所有 xt_node 都 xt_update() 一遍,就變成 AVL-Tree。但是這樣會增加 st_update() 的時間。
5. 把 nodeA 用 nodeB 取代:屬於一種 node 刪除法
(a) 概念上等於 swap(nodeA, nodeB) 再砍掉 nodeA
(b) nodeB 原本的位置屬於好刪除的,所以先把 nodeA 換過去
6. Insert node 和 Remove node 到 XTree 中
[TODO]
[TODO]