關於數字DP的學習

2021-09-30 11:33:13 字數 2360 閱讀 6012

---恢復內容開始---

因為最近做比賽經常會出現數字dp,便嘗試著去學學看數字dp。

《數字計數問題解法研究》

《**數字類統計問題》

然後也是尋找了很多大牛的部落格,學習了很多(但是沒學會囧。),現在先總結一下已經學到的東西

「在資訊學競賽中,有這樣一類問題:求給定區間中,滿足給定條件的某個d 進製數或

此類數的數量。所求的限定條件往往與數字有關,例如數字之和、指定數碼個數、數的大小

順序分組等等。題目給定的區間往往很大,無法採用樸素的方法求解。此時,我們就需要利

用數字的性質,設計log(n)級別複雜度的演算法。解決這類問題最基本的思想就是「逐位確定」

的方法。下面就讓我們通過幾道例題來具體了解一下這類問題及其思考方法。」——劉聰

事實上,為什麼會想到用數字dp來做,就是因為限定條件往往和數字有關,而仔細地樸素的暴力方法中,所做的重複的工作太多。這樣的條件會使得dp(記憶化搜尋)有用武之地。

目前我所接觸到的大多數的題,都是可以通過記錄某些值(比如數字等)來減少重複的運算。當然,因為此類題的特殊性,可以編寫check函式確定**的正確性。

再偷用某個大牛的一句話:其實數字dp(或者說所有記憶化搜尋)都是可以看做通過搜尋來填滿狀態的值。

首先先想想數字dp的執行模式

如果我們要統計[0,54321]中滿足某個條件的個數,需要將其拆分為

[00000,09999][10000,19999],[20000,29999],[30000,39999],[40000,49999],

[50000,50999],[51000,51999],[52000,52999],[53000,53999],

[54000,54099],[54100,54199],[54200,54299],

[54300,54309],[54310,54319],

[54320,54321]

為什麼要這麼分呢?隨便舉個例子,如果我們統計過了[0000,9999]中的滿足條件(或者其他各種不滿足條件的狀態)的個數,那麼分別在加上字首,就可以判斷出有多少個滿足條件的個數。目的是為了將大的區間劃分為小的區間進行求解。

因此,總結一句話,數字dp減少的運算量為:前面幾位固定,後面幾位可以任意取的個數統計。

比如分析一道簡單題:hdu 3652,通過我這個渣渣的錯誤歷程來分析一些細節上的問題

先貼錯誤**

1 #include2 #include3 #include4

using

namespace

std;

5int dp[20][20][20];6

int num[20];7

int dfs(int pos,int mod,int pre,int stat,int

limit)

17if(!limit) dp[pos][mod][pre]=ans;

18return

ans;19}

20int cal(int

x)27

return dfs(cnt,0,0,0,1

);28}29

intmain()

3038

return0;

39 }

我選取的記錄引數有三個:pos當前處理位,mod字首和餘數,還有前一位的數字pre

但是運算結果卻始終會小於等於正確的答案,為什麼呢?

想了想,發現其實是因為引數含義的問題。

分析一下,如果我將pre作為乙個關鍵引數記錄下來,其實我並不能區分我記錄的是後面幾位能不能隨機取的個數。

即當下一次搜尋到pos,mod,pre的時候,不能確定前面是否有13,或者以前搜尋的dp[pos][mod][pre]中的數的個數是否有13。

因此應該把記錄的引數改為pos,mod,stat(表示為記錄狀態,0為不含13,1為只含前一位為1,2為字首含有13)。

因此得到下面的ac**

#include#include

#include

using

namespace

std;

int dp[20][20][3

];int num[20

];int dfs(int pos,int mod,int stat,int

limit)

if(!limit) dp[pos][mod][stat]=ans;

return

ans;

}int cal(int

x)

return dfs(cnt,0,0,1);}

intmain()

return0;

}

view code

好了講完了

關於數字DP的學習

恢復內容開始 因為最近做比賽經常會出現數字dp,便嘗試著去學學看數字dp。數字計數問題解法研究 數字類統計問題 然後也是尋找了很多大牛的部落格,學習了很多 但是沒學會囧。現在先總結一下已經學到的東西 在資訊學競賽中,有這樣一類問題 求給定區間中,滿足給定條件的某個d 進製數或 此類數的數量。所求的限...

數字dp 學習

pragma comment linker,stack 102400000,102400000 include include include include include include include include include include include include using ...

關於數字DP的個人總結

2.dp pos sta pos表示的是遍歷的數的層數 例如十位百位千位 層數是從大到小的,遍歷到 1層則表示當前的數已經形成,則可以返回當前的數的在問題中所計算出的值temp,sta表示的是對於題目,有些不同的資料可以有的相同的狀態,例如 hdu中的不要62 統計乙個區間中沒有4和62出現的數的數...