[英]How to find the xth decibinary number?
Hackerrank 有一個稱為十進制數的問題,它本質上是具有 0-9 位值的數字,但使用 2 的冪進行冪運算。問題要求我們顯示第 x 個十進制數。 這個問題還有另一個轉折點。 多個十進制數可以等於同一個十進制數。 例如,十進制的 4 可以是十進制的 100、20、12 和 4。
起初,我認為找出給定十進制數有多少個十進制數會很有幫助。 我查閱了這篇文章以獲得一些幫助( https://math.stackexchange.com/questions/3540243/whats-the-number-of-decibinary-numbers-that-evaluate-to-given-decimal-number )。 這篇文章有點難以理解,但后來我也意識到,即使我們有一個十進制數可以有多少個十進制數,這也無助於找到它們(至少據我所知),這是最初的目標問題。
我確實意識到,對於任何十進制數,它的最大十進制數只是它的二進制表示。 例如,對於 4,它是 100。所以蠻力方法是檢查這個范圍內的所有數字的每個十進制數,看看它們的十進制表示是否計算為給定的十進制數,但很明顯,這種方法永遠不會由於輸入約束將 x 定義為從 1 到 10^16,因此通過。 不僅如此,我們還必須為 aq 數量的查詢找到第 x 個十進制數,其中 q 從 1 到 10^5。
這個問題屬於 dp 部分,但我很困惑如何使用 dp 或者它是如何可能的。 為了計算第 x 個十進制數 q 次(在上面的蠻力方法中進行了描述),最好使用一個表格(就像問題所暗示的那樣)。 但為此,我們需要存儲和計算 10^16 個整數,因為這就是 x 的大小。 假設 integer 是 4 字節,4B * 10^16 ~= 4B * (2^3)^16 = 2^50 字節。
有人可以解釋一下如何以最佳方式解決這個問題。 我還是 CP 的新手,所以如果我在某些方面犯了錯誤,請告訴我。
(有關完整的問題說明,請參見下面的鏈接): https://www.hackerrank.com/challenges/decibinary-numbers/problem
這可以用大約 80 MB 的數據來解決。 我不會給出代碼,但我會解釋策略。
構建一個查找count[n][i]
,它為您提供使用前i
位獲取十進制數n
的方法的數量。 您首先在任何地方插入0
,然后在count[0][0]
中放入1
。 現在開始使用規則填寫:
count[n][i] = count[n][i-1] + count[n - 2**i][i-1] + count[n - 2*2**i][i-1] + ... + count[n - 9*2**i][i-1]
事實證明,您只需要前 19 位數字,並且您只需要n
最多2**19-1
的計數。 並且計數都適合 8 字節long
的 s。
一旦你有了它,創建第二個數據結構count_below[n]
,它是多少十進制數將給出小於n
的值的計數。 使用與以前相同的n
范圍。
現在查找進行如下。 首先,您對count_below
進行二分搜索,以找到最后一個小於目標數的值。 從您的查詢中減去count_below
,您就知道您想要該值的哪個十進制數。
接下來,搜索count[n][i]
以找到i
,這樣您就可以得到具有i
位而不是更少的目標查詢。 這將是您答案的首位數字的 position。 然后從查詢中減去count[n][i-1]
(所有位數較少的十進制數)。 然后減去count[n-2**i][i-1]
, count[n-2* 2**i][i-1]
, ... count[n-8*2**i][i-1]
直到你找到那個前導數字是什么。 現在,您從該值中減去該數字的貢獻,並重復邏輯以找到具有較少數字的較小值的正確十進制。
這是一個工作示例來澄清。 首先是前 3 位和最多2**3 - 1
的數據結構:
count = [
[1, 1, 1, 1], # sum 0
[0, 1, 1, 1], # sum 1
[0, 1, 2, 2], # sum 2
[0, 1, 2, 2], # sum 3
[0, 1, 3, 4], # sum 4
[0, 1, 3, 4], # sum 5
[0, 1, 4, 6], # sum 6
[0, 1, 4, 6], # sum 7
]
count_below = [
0, 1, 2, 4, 6, 10, 14, 20, 26, ...
]
讓我們找到第20個。
count_below[6]
是 14 並且count_below[7]
是 20 所以我們的十進制和是6
。20 - count_below[6] = 6
十進制,十進制和為 6。count[6][2]
是 4 而count[6][3]
是 6 所以我們有一個非零的第三個數字。count[6][3] - count[6][2] = 2
第三位非零。count[1][6 - 2**2]
是 2,所以 2 有第三個數字 1。2
的第二個十進制。count[2][1]
是 1, count[2][2]
是 2,所以它有一個非零的第二個數字。count[2][2] - count[2][1] = 1
st 具有非零的第二個數字。2 - 2**1 = 0
。因此你會發現答案是 110。
現在對於這么小的數字,這是很多工作。 但即使是最困難的查找,您也只需要大約 20 步的二進制搜索來找到您的十進制和,另外 20 步來找到第一個非零數字的 position,並且對於這些數字中的每一個,您將必須進行 1-9 次不同的計算才能找到該數字。 這意味着只有數百次計算才能找到數字。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.