POJ 3286 How many 0's?(数论)

Description
给两个32位无符号型整数n和m,保证m<=n,问从m到n中的所有整数中(包括n和m),每个数所包含的0的个数的和
Input
多组输入,每组用例两个无符号整形m和n,以-1 -1结束输入
Output
对于每组用例,输出区间[m,n]中所有数所包含0的个数
Sample Input
10 11
100 200
0 500
1234567890 2345678901
0 4294967295
-1 -1
Sample Output
1
22
92
987654304
3825876150
Solution
首先转化成求 [0, x] 中所有数中,含有的0的个数
对于一个数x,限制每一位是 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
以此类推即可
Code

#include<stdio.h>
typedef long long ll;
ll init(ll m)
{
    ll sum=0,k=10,k1=1;
    while(m/k)
    {
        sum+=(m/k*k1);
        if((m/k1)%10==0)
            sum-=(k1-1-m%k1);
        k*=10;
        k1*=10;
    }
    return sum;
}
int main()
{
    ll m,n,m1,n1;
    while(scanf("%lld %lld",&m,&n)!=EOF)
    {
        if(m<0||n<0) break;
        m--;
        if(m<0) m1=-1;
        else m1=init(m);
        n1=init(n);
        printf("%lld\n",n1-m1);     
    }
    return 0;
}

你可能感兴趣的:(POJ 3286 How many 0's?(数论))