數字dp裸題的套路

2021-08-10 07:27:58 字數 1491 閱讀 6897

首先根據題目的要求初始化

一般為:

for(int i = 0;i <= 1;i ++) dp[1][i] = 1;

for(int i = 1;i <= 最大數的位數;i ++)

for(int j = 0;j <= 9;j ++)

for(int k = 0;k <= 9;k ++)

if(......)//題目要求

dp[i][j] += dp[i-1][k];

dp[i][j]表示不大於位數為i且最高位為j的方案總數。

但是對於最高位,我們並不總是能取得以它為開頭的全集(19999……這一類除外)

不過,如果去掉最高位,我們所列舉的數都是合法的。所以可以直接列舉每一位1 ~ 9的答案就好了。

對於其他的數如果我們沒有方法直接統計,或許我們要想辦法把他拆開。

舉個例子,對於 24653這組數。

因為我們有5位數,所以對於前四位是一定會包含的。

所以我們列舉之前每一位數以1~9為最高位的答案(若不允許含前導0)。

在這裡,對於最高位,我們只加上以1位最高位的答案。(因為以2為最高位並不能列舉到所有的數)

然後我們假定最高位為2,加上次高位以0~3為下一位的答案。

然後我們假定前面的數為24,……

然後對於最後一位的3我們怎麼處理,難道這個3不要了?

那就不要了吧,寫開區間吧,我們求24654這個數。

對了,有乙個細節,如果對於某一枚舉的數字自身已經不符合要求了。

由於我們的每一位都會帶到下一位,所以後面的一定不符合條件,要直接跳出。

例如我們要求不大於某乙個數中相鄰兩個數不大於2的個數,對於12347666這個數如果我們已經假定前幾

位分別是12347,那麼對於後面的數無論我們選什麼都是不成立的,所以直接break;

#include

#include

#include

#include

#include

using

namespace

std;

int a,b,ans,cnt,jl[105],dp[105][105];

void init()//數字dp的套路,按照題目要求初始化。

int tj(int x)//這是乙個開區間的。

//拆分x

for(int i = 1;i < cnt;i ++)

for(int j = 1;j <= 9;j ++)

ans += dp[i][j];//如果去掉最高位,我們所列舉的數都是合法的。

for(int i = 1;i < jl[cnt];i ++) ans += dp[cnt][i];//最高位到第jl[cnt-1]位為止還是全集。

for(int i = cnt - 1;i >= 1;i --)//假設上一位已經確定為jl[i+1]。

return ans;

}int main()

HDU 3652 數字DP 套路題

題意 統計能被13整除和含有13的數的個數 解法沒法好說的.學了前面兩道直接啪出來了 ps.hdu深夜日常維護,沒法交題,拿網上的 隨便對拍一下,輸出一致 include define rep i,j,k for register int i j i k i using namespace std ...

HDU 1520 樹形dp裸題

1 hdu 1520 anniversary party 2 總結 第一道樹形dp,有點糾結 題意 公司聚會,員工與直接上司不能同時來,求最大權值和 include include include include include include define max a,b a b?a b usin...

數字dp 板子題

題目傳送 存乙個狀態就可以了,用來判斷前一位是不是6的情況 具體看 注釋 ac include inline long long read while c 0 c 9 return x s using namespace std define newnode treenode malloc size...