數字dp入門 本校woj 1120 數字計數

2021-09-10 03:53:09 字數 1897 閱讀 7201

描述

給定兩個正整數a和b,求在[a,b]中的所有整數中,每個數碼(digit)各出現了多少次。

//基礎的數字dp

記憶化思路比較清晰

注意前導0的特判

遞推拆分比較複雜,需要結合題意思考統計方式

(預處理無腦)

遞推:

#include

#include

#include

using

namespace std;

#define int long long

const

int n=14;

int f[n]

[n][n]

;int t[n]

;inline

void

pre()}

f[i]

[j][j]

+=t[i-1]

;//注意放在迴圈外面 }}

}int bit[n]

,ansl[n]

,ansr[n]

;inline

void

getans

(int n,

int ans)

// 預處理 前導零的情況 (最高位是0,那麼所有討論的子第一位都不能是0)

//如果忽略前導零,那麼都當作len位數處理

//如果前導零有實際含義,就要單獨處理1~len-1位數(相當於在前面加0)

//也可以放在下面處理,只是碰到0特判有點麻煩

for(

int i=

1;i<=len-1;

++i)}}

for(

int i=len;i>=1;

--i)

} res%

=t[i-1]

;//算出1~i-1位的值

ans[bit[i]]+

=res+1;

//迴圈帶來是結果:所有都是最高位被忽略

// 但由於題目的特性,會單獨統計最高位的貢獻,故最高位被忽略無影響。

//首先,當前j=bit[i],只能累加i-1位的權值總和。

//所以當前位的當前數沒有被計入

//當前共有 0~[i-1][i-2][...][1]

//和預處理的10^(i-1)不同,此處通過取模得到的是最大值,

//從0開始,還需+1 }}

//預處理的時候,用狀態轉移即可

//在拆分的時候一定要注意:

//細節太多:

//1. 注意迴圈的本質就保證了

signed

main()

return0;

}

記憶化:

#include

using

namespace std;

#define int long long

const

int n=20;

int f[n]

[n][n]

,bit[n]

,l,r;

intdfs

(int loc,

int num,

int sum,

bool zero,

bool up)

return((

!zero)&&(

!up)

)?f[loc]

[num]

[sum]

=res:res;

}inline

intgetans

(int n,

int k)

return

dfs(len,k,0,

1,1)

;}signed

main()

return0;

}

數字DP入門 數字DP模板

數字dp是一種計數用的dp,一般就是要統計乙個區間 le,ri 內滿足一些條件數的個數。所謂數字dp,字面意思就是在數字上進行dp咯。數字還算是比較好聽的名字,數字的含義 乙個數有個位 十位 百位 千位.數的每一位就是數字啦!之所以要引入數字的概念完全就是為了dp。數字dp的實質就是換一種暴力列舉的...

數字DP入門

數字dp顧名思義就是對數字運用dp思想,將每位數看成下一位的子狀態,即個位看成十位的子狀態,十位看成百位的子狀態。下面給出狀態方程 dp i j dp i 1 k k 0,1,2,3.9 dp i j 表示i位數,首位是j的數字有多少符合要求的,我們從低位逐步遞推求到高位。下面拿一道入門題來具體說明...

數字dp入門

數字dp,顧名思義 對數的位數進行操作。一般 題目會與數的位數相關。數字dp最重要的是其dp陣列的確定,根據需要 可以確定多維dp陣列,一般dp陣列的每一對下標 都只能唯一確定乙個狀態,或者 對結果並不影響。dp陣列一定會有一維表示 當前列舉到的 位數。模版 如 此處設立的dp陣列為二維 int d...