UVa 1640 The Counting Problem (数位dp)
题目链接:https://acm.hdu.edu.cn/showproblem.php?pid=1663
记录一下某数字出现的次数,每个数字都单独算一遍即可
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 30;
int l, r;
ll dp[maxn][maxn], ans[maxn];
vector<int> dig;
ll dfs(int pos, int num, int ans, int lead, int lim){
if(!pos) {
return ans;
}
if(!lim && !lead && dp[pos][ans] != -1) return dp[pos][ans];
int limit = lim ? dig[pos] : 9;
ll res = 0;
for(int i = 0 ; i <= limit ; ++i){
if(lead && i == 0) res += dfs(pos-1, num, 0, 1, lim && (i==limit));
else res += dfs(pos-1, num, ans + (i == num), 0, lim && (i==limit));
}
if(!lead && !lim) dp[pos][ans] = res;
return res;
}
ll solve(int x, int num){
dig.clear();
memset(dp, -1, sizeof(dp));
dig.push_back(-1);
int tmp = x;
while(tmp){
dig.push_back(tmp % 10);
tmp /= 10;
}
return dfs(dig.size()-1, num, 0, 1, 1);
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(scanf("%d%d", &l, &r) == 2 && l){
if(l > r) swap(l, r);
for(int i = 0 ; i <= 9 ; ++i){
printf("%lld%c", solve(r, i) - solve(l-1, i), i == 9 ? '\n' : ' ');
}
}
return 0;
}