题目大意:给定一个正数区间,要你求这个区间,包含区间两端点的十进制表示0的个数和
解题思路:假设区间[a, b],求0 ~ a - 1的这些数中0的个数,0~b的这些数中0的个数,然后把他们相减即为所求。
若a为0时,只要求0~b的0的个数就可以了。
求某个数,比如4位数abcd,只要求每位数对0的个数的贡献就行
比如3421,百位数对0的贡献有:1000,1001...1099,2000,2001,...,2099,3000~~~3099,即为3 * 100 = 300个
若是3021,百位数对0的贡献有:1000,1001....1099, 2000,2001,...,2099, 3000~~~3021,即为(3-1) * 100 + 21 + 1个
所以要求某位对0的贡献,当这一位为0时,贡献0的个数为(高位的数值 - 1) * 10^(低位的位数) + 低位数值 + 1个
当某位不为0时,贡献为 高位数值 * 10^(低位的位数)
#include <iostream>
#include <cstdio>
using namespace std;
long long sum0(long long n);
int main()
{
long long ans = 0;
long long st, ed;
while(true)
{
scanf("%lld %lld", &st, &ed);
if(st == -1 && ed == -1)
break;
if(st == 0)
printf("%lld\n", sum0(ed));
else
printf("%lld\n", sum0(ed) - sum0(st - 1));
}
return 0;
}
long long sum0(long long n)
{
if(n == 0)
return 1;
long long factor = 1;
long long lowerNum = 0;
long long curNum = 0;
long long highNum = 0;
long long num = 1;
while(n / factor != 0)
{
lowerNum = n % factor;
curNum = (n / factor) % 10;
highNum = n / (factor * 10);
switch(curNum)
{
case 0:
num += (highNum - 1) * factor + lowerNum + 1;
break;
default:
num += highNum * factor;
break;
}
factor *= 10;
}
return num;
}
求0~~n的出现1的个数和的分析方法也是一样
比如12013,百位为0,贡献1的数为:100~199, 1100~1199,...,11100~11199。只有高位起作用,所以贡献个数为(11+1)* 10^2
若为12113时,百位为1贡献1的数为:100~199,1100~1199,...,11100~11199,12100~12113。高位和低位都起作用,贡献个数为(11+1)*10^2 + (13 + 1)
若为12313时,百位不为1和0,贡献数为100~199,1100~1199,...,11100~11199,12100~12199。只有高位起作用,贡献个数为(12+1)*10^2
代码实现为
long long sum1(long long n)
{
if(n == 0)
return 0;
long long factor = 1;
long long lowerNum = 0;
long long curNum = 0;
long long highNum = 0;
long long num = 0;
while(n / factor != 0)
{
lowerNum = n % factor;
curNum = (n / factor) % 10;
highNum = n / (factor * 10);
switch(curNum)
{
case 0:
num += highNum * factor;
break;
case 1:
num += highNum * factor + lowerNum + 1;
break;
default:
num += (highNum + 1)* factor;
break;
}
factor *= 10;
}
return num;
}