数位DP

[数位DP]
运用记忆化搜索来对每一位枚举,
一般需要枚举以下几种参数:
id:枚举到第几位。
x:当前位是否与num[id]相等,即当前是否为上限。
zero:是否有前导0
前导0---签到题爆0
sum:其他题目需要的(如\(luogu\) \(P2602\) \([ZJOI2010]\) 数字计数就是求数量)
1.
\(luogu\) \(P2602\) \([ZJOI2010]\) 数字计数
\(accoders\) \(2201\)【一本通提高数位动态规划】数字计数
思路:
要求统计从l到r 每个数字重复了多少遍,
对其进行记忆化搜索,计算出从0到当前的数字有多少个,
然后运用神似前缀和的方法求出总数即可。
\(code:\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[20][2][20][2];
int num[20];
int dfs(int id,int x,int sum,int zero,int number){
	int ans=0;
	if(id==0){
		return sum;
	}
	if(dp[id][x][sum][zero]!=-1){
		return dp[id][x][sum][zero];
	}
	for(int i=0;i<10;i++){
		if(!x&&i>num[id]){
			break;
		}
		ans+=dfs(id-1,x||(i<num[id]),sum+((!zero||i)&&(i==number)),zero&&(i==0),number);
	}
	dp[id][x][sum][zero]=ans;
	return ans;
}
int f(int x,int number){
	int l=0;
	while(x){
		num[++l]=x%10;
		x/=10;
	}
	memset(dp,-1,sizeof(dp));
	return dfs(l,0,0,1,number);
}
signed main(){
	int a,b;
	cin>>a>>b;
	for(int i=0;i<10;i++){
		cout<<f(b,i)-f(a-1,i)<<" ";
	}
	return 0;
}  
posted @ 2025-01-23 20:57  lbh123  阅读(25)  评论(0)    收藏  举报