数字计数 (奇特的数位dp)
给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。
这道题就是枚举第i个数位是什么数字,然后乘法原理搞一搞。小心当前枚举的数位是0的情况,需要特判前导零。
#include <cstdio>
using namespace std;
typedef long long LL;
const LL maxl=14;
LL pow[maxl], ans[10];
LL a, b;
void solve(LL x, LL pos){
if (x==-1){ ans[0]+=1; return; }
LL now, high, low, flag, len=0;
for (; pow[len]<=x; ++len);
for (LL i=0; i<len; ++i){
now=x%pow[i+1]/pow[i];
high=x/pow[i+1]; low=x%pow[i];
for (LL j=0; j<10; ++j){
if (j) flag=0; else flag=1;
if (j==now) ans[j]+=((high-flag)*pow[i]+low+1)*pos;
if (j<now) ans[j]+=((high+1-flag)*pow[i])*pos;
if (j>now) ans[j]+=((high-flag)*pow[i])*pos;
}
}
}
void init_pow(){
pow[0]=1;
for (LL i=1; i<=maxl; ++i)
pow[i]=pow[i-1]*10;
}
int main(){
init_pow();
scanf("%lld%lld", &a, &b);
solve(b, 1); solve(a-1, -1);
for (LL i=0; i<=9; ++i) printf("%lld ", ans[i]);
return 0;
}