数位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;
}

浙公网安备 33010602011771号