数位 DP
数位 DP 统计区间 [0,x] 内满足数字性质的整数,再以 solve(R)-solve(L-1) 得到任意区间答案。按从高到低填数,并记录前缀是否仍贴着 x 的上界。
状态
典型记忆化搜索为 dfs(pos,state,tight,started):pos 是当前位;state 是题目需要的余数、前一位、出现次数或掩码;tight 表示前缀等于上界;started 区分前导零与真正的数字 0。
long long dfs(int p,int mod,bool tight,bool started){
if(p==len) return started && mod==0;
if(!tight && memo[p][mod]!=-1) return memo[p][mod];
int up=tight?dig[p]:9; long long ans=0;
for(int d=0;d<=up;d++) ans+=dfs(p+1,(mod*10+d)%K,tight&&d==up,started||d);
return tight?ans:memo[p][mod]=ans;
}
流程与复杂度
- 把 x 拆成数位;
- 枚举当前位 0 到上界;
- 更新题目状态并递归;
- 只缓存
tight=false的状态。
若状态数为 S、位数为 D,时间 O(10DS)、空间 O(DS)。处理“无前导零”“数字 0 是否计入”“上界为负数”是最常见边界。
整理自 XOJ《数位DP》。