题意:
统计两个整数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 = "CSDN"; *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; }