簡體   English   中英

如何找到第 x 個十進制數?

[英]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個。

  1. count_below[6]是 14 並且count_below[7]是 20 所以我們的十進制和是6
  2. 我們想要20 - count_below[6] = 6十進制,十進制和為 6。
  3. count[6][2]是 4 而count[6][3]是 6 所以我們有一個非零的第三個數字。
  4. 我們希望count[6][3] - count[6][2] = 2第三位非零。
  5. count[1][6 - 2**2]是 2,所以 2 有第三個數字 1。
  6. 第三個數字是1
  7. 我們現在正在尋找十進制和為2的第二個十進制。
  8. count[2][1]是 1, count[2][2]是 2,所以它有一個非零的第二個數字。
  9. 我們希望count[2][2] - count[2][1] = 1 st 具有非零的第二個數字。
  10. 第二個數字是1
  11. rest 為 0 ,因為2 - 2**1 = 0

因此你會發現答案是 110。

現在對於這么小的數字,這是很多工作。 但即使是最困難的查找,您也只需要大約 20 步的二進制搜索來找到您的十進制和,另外 20 步來找到第一個非零數字的 position,並且對於這些數字中的每一個,您將必須進行 1-9 次不同的計算才能找到該數字。 這意味着只有數百次計算才能找到數字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM