数位 dp 总结
用途:统计 \([1,x]\) 中满足某某性质的数的个数。
(当然,如果题目要求统计 \([l,r]\) 中的数,那么用 \([1,r]\) 的答案减 \([1,l-1]\) 的答案即可)
数据范围:\(10^9\) 起步。
状态:现在是第几位(\(x\),并记这一位上的数字为 \(num_x\))、有没有前导零(\(zer\))、能枚举的范围是 \([0,9]\) 还是 \([0,num_x]\)(\(lim\))、根据题目设出来的状态(例如数字出现的个数,模 \(m\) 的余数等等)。
模板:
int dp(int x,bool zer,bool lim,...){
if(x==0)return ...;
if(!~f[x][zer][lim][...])return f[x][zer][lim][...]; // 记忆化
int res=0;
for(int i=0;i<=(lim?num[x]:9);i++){
if(zer&&i==0)res+=dp(x-1,1,lim&&i==num[x],...); // 是前导零
else res+=dp(x-1,0,lim&&i==num[x],...); // 不是前导零
} // 有时我们不关心是不是前导零,此时这两种情况可以合并
return f[x][zer][lim][...]=res;
}
本文来自博客园,作者:registerGen,转载请注明原文链接:https://www.cnblogs.com/registergen/p/digit_dp.html

浙公网安备 33010602011771号