dp專題總結

2021-08-25 02:27:55 字數 3408 閱讀 9105

所有的dp關鍵有兩點

1.看出來這是一道dp題 (看時間複雜度)

2.狀態轉移方程!!!!

其中狀態的確立和推出狀態轉移方程是個難點,而且dp題還經常會和其他知識點融合在一起搞你,非常靈活。

先從有跡可循的一些經典dp問題入手

一.數字dp

1.確立狀態

如何確立乙個正確的dp陣列?

dp[pos][state1][state2][….]

首先第一維代表著數字

若是人為規定的話: 0-個位 1-十位 2-百位 3……

那麼後面的state代表的就是所有的的i位數滿足的性質

eg. 如果要記錄所有四的倍數的數量 (當然有更簡單的容斥做法,這裡只是舉個例子)

開 dp[pos][mod]

那麼dp[3][2]代表著所有千位數(0000-9999)中%4餘2的個數

那怎麼確定我們要開那些狀態?

1.題目中明確要求的

2.影響狀態轉移的(前導0什麼的)

例如

每組資料只有一行,包含三個整數 l_i,r_i,m。

在 [l_i,r_i ] 區間,有多少個數奇偶和等於 m,以及這些數的和(對和取模100000007後輸出)。

描述 給定乙個數 x,設它十進位制展從高位到低位上的數字依次是 a0, a1, …, an - 1,定義交錯和函式:

f(x) = a0 - a1 + a2 - … + ( - 1)n - 1an - 1

例如:

f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4

給定 l, r, k,求在 [l, r] 區間中,所有 f(x) = k 的 x 的和,即:

這兩道題非常像,但是不同的地方導致我們的狀態方程也不一樣。

先考慮第一道題:

對於pos位,我們想要得到答案dp[pos][sum] 只需從dp[pos-1][sum-sgn*i]轉移而來,用**來表示的話,就是:

for(int i=0; i<=up; i++)

dp[pos][sum]:pos位數中滿足奇偶和是sum的個數與其總和

我們只需開多開一維sum記錄 pos位數中滿足奇偶和是sum的個數

當前的加減與當前的i有關,與之前和之後的數無關,轉移並不會衝突。

第二道題:

我們能否也和上一題一樣也開 dp[pos][sum]呢?

那好,先來解釋一下 如果只開兩維 dp陣列的意義:

pos位數滿足交錯和為sum時的個數和總和

乍一看沒問題,但當你寫狀態轉移的時候,就會發現狀態該怎麼轉移?

狀態沒法轉移,當前是加,那麼下一位就是減,反之亦然。你沒有辦法區分當前是正是負 還是前導0,當前狀態的不同會導致之後狀態也不一樣。

所以給每個數再加上個性質:當前位的符號

dp[pos][sum][sgn]

sgn: 0-有前導0 ,1-正, -1 負

struct nodedp[30][500][3]; //偏移量240

//第三維代表lead

int a[30];

ll pow[30];

int k;

//lead 0-有前導0 1-正 -1 負

node dfs(int pos,bool limit,int lead,int sum)

; }

if(!limit&& dp[pos][sum+240][lead].num!=-1) return dp[pos][sum+240][lead];

node ans=node;

int up=limit?a[pos]:9;

for(int i=0;i<=up;i++)

return limit?ans:dp[pos][sum+240][lead]=ans;

}ll solve(ll x)

return dfs(pos-1,1,0,k).sum;

}

其他難以確立的狀態還有很多,比如大都會的四維dp,比如各種模數,連續字串。

但最為關鍵的就是記住dp[pos][state1][state2][…]

每多乙個狀態,那麼就是pos位的數進一步被細分,可以看做是各種性質的交集,怎麼去分這個數,就是確立狀態的關鍵。

2.狀態的轉移

其實狀態的轉移多多少少要在確立這個狀態的時候一併考慮到了,畢竟狀態要能正確的轉移,我們才能說這個確立的狀態是對的嘛。

而數字dp的轉移是比較單純的,因為多半就是從高位到地位列舉,從低位到高位轉移,而我們一般都是用數字dp記錄滿足條件數的個數,轉移比較簡單,寫出dp陣列,一般轉移就出來了。

那如果要記錄所有滿足條件數的總和,平方和,別的什麼奇奇怪怪的東西呢?

額,目前就遇到過 和 與 平方和。

和:當前列舉的數×當前的位權×(要轉移到的)低位的滿足某性質的個數+(要轉移到的)低位的滿足某性質的個數

eg:。。。。x 。。。

令x1-xn都是滿足條件的低一位的數

sum = (x+x1)+(x+x2)+

⋯ ⋯

(x+xn) =n×x + x1+

⋯ ⋯

+xn開個struct 記錄num和sum

平方和:

ans

= =

(x+x1)2

' role="presentation" style="position: relative;">(x+

x1)2

(x+x

1)2+

(x+x

2)2 (x+

x2)2

+ ⋯ ⋯

+ (x

+xn)

2 (x+

xn)2

==

n∗x2+2∗

x∗(x

1+x2

+⋯+x

n)' role="presentation" style="position: relative;">n∗x

2+2∗

x∗(x

1+x2

+⋯+x

n)n∗

x2+2

∗x∗(

x1+x

2+⋯+

xn)所以要維護三個值:個數 總和 平方和

eg 二概率dp(期望dp)

感覺都可以用數學簡化,但數學功底不夠,就用dp來湊

dp專題總結

1 做題感覺 大部分時候看到題感覺一頭霧水,在明確告訴這是動態規劃的題時會刻意往這方面想,縮小問題規模。如果沒說的話,可能根本不會朝這方面去想。感覺好難做起來理解起來都很費勁,專題中有很多題是稍微變了一下,就暈了,會在各方面細節出問題。就像登山問題和合唱團問題,感覺他們一模一樣,樣例也通過了,就是過...

總結 筆記 題解 DP專題

c est dur.數字 dp 主要求解的是在給定區間 l,r 中滿足條件的解的個數這一類問題.我們一般把求區間 l,r 轉換成求區間 0,r 和 0,l 1 再將得到的結果相減就是答案.對於 不要62 這個問題,我們可以設 f i j 表示位數為 i 開頭的數為 j 的情況下滿足條件的答案數,但要...

數字DP專題

hdu 2089 不要62 hdu 3555不能出現連續的49 uestc 1307相鄰的數差大於等於2 hdu 3652 出現13,而且能被13整除。hdu 3709平衡數 light oj 1140兩個數之間的所有數中零的個數。lightoj 1032 二進位制數中連續兩個 1 出現次數的和 c...