题目传送门:https://www.luogu.com.cn/problem/P2602 题解: 数位dp 对于每个数(0~9)进行一次数位dp 由于 前面的数码出现的次数 会影响到最后结果 所以将 前面的数码出现的次数 设为dp的第二维状态 然后记录对应结果,输出相减值即为答案
代码及注释如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll a[20],dp[20][20],ans[3][10];
int now;
ll dfs(int pos, bool lim, bool zero, int now,ll num) {
if(pos==0) return num;
if(!lim&&!zero&&dp[pos][num]!=-1) return dp[pos][num];
ll ans = 0,add = 0;
int siz = lim?a[pos]:9;
for(int i = 0;i <= siz;i++) {
if(!now&&zero&&i==0) add = 0;
else add = i==now;
ans += dfs(pos-1, lim&&i==a[pos], zero&&i==0, now, num+add);
}
if(!lim&&!zero) dp[pos][num] = ans;
return ans;
}
void solve(ll val) {
int pos = 0;
while(val) {
a[++pos] = val%10;
val /= 10;
}
for(int i = 0;i <= 9;i++) {
memset(dp, -1, sizeof(dp));
ans[now][i] = dfs(pos, 1, 1, i, 0);
}
now ^= 1;
}
int main() {
ll a,b;
cin>>a>>b;
solve(b);
solve(a-1);
for(int i = 0;i <= 9;i++) cout<<ans[0][i]-ans[1][i]<<" ";
return 0;
}
|