poj 3286

来源:互联网 发布:网络监控是什么 编辑:程序博客网 时间:2024/05/22 01:38

         题意:给一个区间[x,y],输出区间内所有数字中0~9各自出现的个数。

        分析:只要求出[0,n]内的解就行了,假设n=23456,统计4出现的个数,

                    当4在个位时,左边可以填0~2345,右边没有,ans+=2345+1,

                    当4在百位时,左边可以填0~234,因为5大于4,所以右边可以填0~9,ans+=(234+1)*10

                    当4在千位时,左边可以填0~23,因为4等于4,所以,当左边取0~22时,右边可以取0~99,当左边取23时,右边只能取0~56,ans+=(22+1)*100+56+1,

                    当4在万位时,左边只能填0~1,右边可以取0~999,所以ans+=(1+1)*1000.

                    .......

                   依次类推,就可以统计1~9出现的个数,在统计0时,因为0不能作为开头,所以只需把left-1就行了。

  代码如下:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>#include <queue>#include <map>#include <set>#include <cmath>using namespace std;typedef long long ll;const int N=1000;int c[N][N];ll f[13],l,r;void init(){    int i,j;    f[0]=1;    for (i=1;i<14;i++) f[i]=f[i-1]*10;}ll slove(ll n,int k){    int i,j;    ll ans=0;    for (i=1;i<13;i++) {        int left=n/f[i]-(k==0);        ans+=left*f[i-1];        int d=(n%f[i]-n%f[i-1])/f[i-1];        if (d>k) ans+=f[i-1];        else if (d==k) ans+=n%f[i-1]+1;        if (n<f[i]) break;    }    return ans;}int main(){    int i,j;    init();    while(~scanf("%lld%lld",&l,&r))    {        if (l>r) swap(l,r);        if (!l && !r) break;        for (i=0;i<9;i++)            cout<<slove(r,i)-slove(l-1,i)<<" ";        cout<<slove(r,9)-slove(l-1,9)<<endl;    }}


0 0
原创粉丝点击