描述
給定兩個正整數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...