首页 > 代码库 > UVA 11038 - How Many O's?(计数问题)

UVA 11038 - How Many O's?(计数问题)

题目链接:11038 - How Many O‘s?

题意:求[a.b]之间,0出现的次数。
思路:一开始一直往数位DP上去想,结果发现挺复杂的。。
把问题先转化为求0 - num的个数,在用到b的个数减去到a的个数
其实只要利用计数的乘法和加法原理,把数字对应的每一位的分成左右两边,利用乘法原理求总数,在用加法原理把所有的总数加起来就是总情况数。那么讨论一下分成两边的情况。举个例子
比如23045
设中间位为mid,如果mid不为0,假如求到4这个位,那么左边的情况就有[1-230]种情况,而右边则有[0 - 9]种情况,再如果求到3这个位,左边就有[1- 2]种,右边有[0 - 999]种,因为右边不管怎么取都不会超过数字。
如果mid为0,那么左边取[1-22]时,右边可以随便取为[1-100],如果左边取23,右边只能取[0-45]。这样总情况由低位一直往高位去计算就能算出来了
代码:
#include <stdio.h>
#include <string.h>

long long a, b;

long long solve(long long left) {
	if (left < 0) return 0;
	long long ans = 1, mid, right = 0, j = 1;
	while (left >= 10) {
		mid = left % 10; left /= 10;
		if (mid) ans += left * j;
		else ans += (left - 1) * j + right + 1;
		right = right + mid * j;
		j *= 10;
  	}
  	return ans;
}

int main() {
	while (~scanf("%lld%lld", &a, &b) && a != -1 || b != -1) {
		printf("%lld\n", solve(b) - solve(a - 1));
 	}
	return 0;
}