题意:
a,b之间各个数字(0~9)出现的次数,如1024和1032,他们之间的数字有1024 1025 1026 1027 1028 1029 1030 1031 1032 总共有10个0,10个1,3个3等等。
分析:
0的干扰,为了计算方便暂时都先计算在内,之后再减;
0~199,那么百位上的0和1各出现一次,s剩下的就是两个00~99,总共两百个二位数,而每个数出现的次数都一样,都是2*(99-00+1)/10;
3426,则可以分成0000~2999,3000~3399,3400~3419,3420~3426几个部分各自计算,再求和按位减去前导0的个数。
#include <iostream>
#include <cstdio>
using namespace std;
/**
* 计算从0到s字符串所代表的数字中0~9各个数字出现的次数..
*
*/
void cal(char s[], int num[]) {
int i, j, k, n, t, m = atoi(s);//atoi(s).把字符串转换成整型数。ASCII to integer 的缩写。
n = (int) strlen(s);
for (i = k = 1; i < n; i++)
k *= 10, num[0] -= k;
for (i = 0; i < n; i++, k /= 10) {
for (j = 0; j < s[i] - '0'; j++)
num[j] += k;
for (t = 0; t < 10; t++)
num[t] += k / 10 * (n - i - 1) * j;
if (i + 1 < n)
num[j] += atoi(s + i + 1);
num[j]++;
}
}
int main() {
int n, m;
int a[11], b[11];
char str[25];
while (scanf("%d%d", &n, &m) != EOF, n || m) {
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
if (n > m) {
int temp = n;
n = m;
m = temp;
}
/**
* 函数功能:把格式化的数据写入某个字符串
* 函数原型:int sprintf( char *buffer, const char *format [, argument] … );
* 返回值:字符串长度(strlen)
*例子:
*char* who = "I";
*char* whom = "";
*sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. " 这字符串写到s中
*sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"
*/
sprintf(str, "%d", n - 1); //将格式化的数据写入某个字符串
cal(str, a);
sprintf(str, "%d", m);
cal(str, b);
int i;
for (i = 0; i < 10; ++i) {
printf("%d ", b[i] - a[i]);
}
printf("\n");
}
return 0;
}