(Realx 数论1.28)POJ 2282 The Counting Problem(区间统计数字:统计a、b之间各个数字(0~9)出现的次数)

来源:互联网 发布:死神镰刀1.5米淘宝 编辑:程序博客网 时间:2024/05/30 04:54


题意:

  统计两个整数a,b之间各个数字(0~9)出现的次数,如1024和1032,他们之间的数字有1024 1025 1026 1027 1028 1029 1030 1031 1032 总共有100,10133等等。

分析:

  因为前导0的干扰,为了计算方便暂时都先计算在内,之后再减;

  如果是0~199,那么百位上的01各出现一次,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;}


原创粉丝点击