https://vjudge.net/problem/UVA-1640
题目
给两个数字$a$,$b$,问将$[a,b]$之间的数字写成一行,数字0、1、2、3、4、5、6、7、8、9各出现多少次。$nleqslant 10^8$,500组数据
题解
分两种情况,考虑每一位……
举个例子,如果给的数字是203,考虑1出现多少次。
考虑个位,那么出现的情况是$20oxed{1}sim phantom{00}oxed{1}$,$20-0+1$次
考虑十位,那么出现的情况是$1oxed{1}9sim phantom{0}oxed{1}0$,$19-0+1$次
考虑百位,那么出现的情况是$oxed{1}99simoxed{1}00$,$99-0+1$次
其他的情况也要考虑……这只是举例= =
AC代码
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<cassert> #include<algorithm> #define REP(i,a,b) for(register int i=(a); i<(b); i++) #define REPE(i,a,b) for(register int i=(a); i<=(b); i++) #define PERE(i,a,b) for(register int i=(a); i>=(b); i--) #ifdef sahdsg #define DBG(...) printf(__VA_ARGS__) #else #define DBG(...) (void)0 #endif #define ln log using namespace std; typedef long long LL; int a,b; int f0(int x) { int k; int ans=0; for(int i=1; i<=x; i*=10) { k = x/i/10*i; if(k*10+i-1<=x) k+=i-1; else k+=x%i; if(k>=i) ans+=k-i+1; } return ans; } int f(int x, int q) { int k; int ans=0; for(int i=1; i*q<=x; i*=10) { k = x/i/10*i; if(k*10+i*q>x) k-=i; if(k*10+i*q+i-1<=x) k+=i-1; else k+=x%i; ans+=k+1; } return ans; } int main() { while(~scanf("%d%d", &a, &b) && a) { if(a>b) swap(a,b); printf("%d", f0(b)-f0(a-1)); REP(i,1,10) { printf(" %d", f(b,i)-f(a-1,i)); } putchar(' '); } return 0; }