POJ 3286 How many 0's?(数位统计)
题目大意
给两个32位无符号型整数 n 和 m,保证 m<=n,问,从 m 到 n 中的所有整数中(包括 n 和 m),每个数所包含的 0 的个数的和
例如:1030 有两个 '0'
做法分析
首先转化成求 [0, x] 中所有数中,含有的 0 的个数
那么对于一个数 x,怎么求出从 0 到 x 中所有数含有 0 的个数的和呢?
我们可以限制每一位是 0,然后再来计算。举个例子,假设 x 是 21035
首先 0 肯定是一个,sum 赋初值为 1
个位数是 0
个位数前面的数不能是 0,能够取的数就是 [1, 2103],个位后面没有了
那么 sum+=2103*1
十位数是 0
十位数前面的数不能是 0,能够取的数就是 [1, 210],由于 0 比 3 小,十位后面可以取 [0, 9]
那么 sum+=210*10
百位数是 0
百位数前面的数不能是 0,能够取的数就是 [1, 21],由于 0 是等于 0 的,这里就要特殊处理下了:
百位数前面的数如果是在 [1, 20] 中的,百位数后面的数可以取的就是 [0, 99]
百位数前面的数如果取的是 21,百位数后面的数就只能取 [0, 35]
那么,sum+=20*100+36
......
相信手推到这里了,读者已经能够明白怎么操作了
参考代码
POJ 3286
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 7 typedef long long LL; 8 9 LL radix[15], n, m; 10 11 LL cal(LL x) 12 { 13 if(x<0) return 0; 14 LL sum=1; 15 for(int i=1; 1; i++) 16 { 17 if(radix[i]>x) break; 18 LL quo=x/radix[i]; 19 LL rem=x%radix[i-1]; 20 LL now=(x%radix[i]-x%radix[i-1])/radix[i-1]; 21 if(now==0) sum+=(quo-1)*radix[i-1]+rem+1; 22 else sum+=quo*radix[i-1]; 23 } 24 return sum; 25 } 26 27 int main() 28 { 29 radix[0]=1; 30 for(int i=1; i<15; i++) radix[i]=radix[i-1]*10; 31 while(scanf("%I64d%I64d", &m, &n), n!=-1 || m!=-1) 32 printf("%I64d\n", cal(n)-cal(m-1)); 33 return 0; 34 }
AC通道