数字计数问题(算法实验)

来源:互联网 发布:行业经济数据对比 编辑:程序博客网 时间:2024/04/29 06:33

数字计数问题

时间限制:3000 ms  | 内存限制:65535 KB

描述

一本书的页码从自然数1开始顺序编码到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6页用数字6表示,而不是06或者006等。数字计数问题要求对给定书的总也码n,分别计算出0,1…,9总共出现的次数

输入

给定的页码n 0<n<10000000

输出

分别输出0,1…,9出现的总次数

样例输入

99

样例输出

9 20 20 20 20 20 20 20 20 20

要求

         不能直接从1循环到n,对每个数字计算0~9出现的次数。

/*算法实验题,我觉得蛮难的蛮麻烦的=_=(对于算法课来说),或者是我太水.>_<,想去网上看人家怎么破才比较简单,没找到,或者我搜索能力也是很水=_=dp[i][j][k] ,表示长度为 i , 以 j 开头 , k 用的次数转移 dp[i][j][k] = 求和(dp[i-1][u][k])  0 <= u <= 9 dp[i][j][j] += 10^(i-1) ;因为不能有前导 0 ,所以我们开了 hehe数组hehe[i][j] 表示长度为 i-1 的所以数 , j 用的次数 然后对于 n , == 不好解释,取个例子 n = 2345 先把 n 的各个位拿出来对于 0 开头的,直接取 hehe[3][]对于 1 开头的,都可以取了 就是 dp[4][1][]对于 2 开头的,2 能去 345 (2345%1000) 个然后 就是 2 开头下面的 2X1X2X3 x1 = 0 ,在 hehe 里面已经算了 x1=1,2都可以取 对于 x1 = 3 , 3 能取 45(2345%100) 个 然后对于 23X2X3 ....一直这样下去ps: 测试了很多数据是对的,没有oj可以交,所以不能保证所有的都是对的,
助教应该看不到的吧,hehe
by 20120125*/
//E


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<ctime>
#define maxn 110
#define LL long long
using namespace std ;


LL dp[12][12][12] ,hehe[12][12] ;
int ans[12] ;
int get( int n )
{
    int ans = 1 ;
    for( int i = 1 ; i <= n ;i++ )
        ans *= 10 ;
    return ans ;
}
void init()
{
    int i ,j, k ,u ;
    memset(dp,0,sizeof(dp)) ;
    memset(hehe,0,sizeof(hehe));
    for( i = 0 ; i < 10 ;i++ ){
        dp[1][i][i] = 1 ;
        for( j = 0 ; j < 10 ;j++ )
            hehe[2][j] = 1 ;
    }
    for( i = 2 ; i <= 10 ;i++ )
    {
        for( j = 0 ; j < 10 ;j++ )
        {
            for( k = 0 ; k < 10 ;k++ )
                 for( u = 0 ; u < 10 ;u++ )
                     dp[i][j][k] += dp[i-1][u][k] ;
            dp[i][j][j] += get(i-1) ;
        }
        for( j = 0 ; j < 10 ;j++ )
            hehe[i+1][j] = hehe[i][j] ;
        for( j = 1 ; j < 10 ;j++ ){
            for( u = 0 ; u < 10 ;u++ )
                hehe[i+1][u] += dp[i][j][u] ;
        }
    }
}
int find( int u , int n )
{
    int i , t = 1 ;
    for( i = 1 ; i < u ;i++)
        t *= 10 ;
    return n%t ;
}
void getans( int n )
{
    int bit[19] ,i,k , m = n,j ;
    memset(ans,0,sizeof(ans)) ;
    k = 1 ;
    while(n)
    {
        bit[k++] = n%10 ;
        n /= 10 ;
    }
    for( i = 0 ; i < 10 ;i++ )
        ans[i] = hehe[k-1][i] ;
    for( i = k-1 ; i >= 1 ;i-- )
    {
        if(i==k-1) j =1 ;
        else j = 0 ;
        for( ; j < bit[i] ;j++)
          for( k = 0 ; k < 10 ;k++)
            ans[k] += dp[i][j][k] ;
         ans[bit[i]] += find(i,m)+1 ;
       //  for( j = 0 ; j < 10 ;j++)
         //   ans[j] += hehe[i][j] ;
    }
}


void zhe( int n )//暴力
{
    memset(ans,0,sizeof(ans)) ;
    for( int i = 0 ;  i<= n ;i++ )
    {
        int m = i ;
        while(m)
        {
            ans[m%10]++ ;
            m /= 10 ;
        }
    }
}
int main()
{
    int i,j ,n ;
//freopen("in.txt","r",stdin) ;
int tt=clock() ;
    init();
    while( scanf("%d",&n) != EOF )
    {
        getans(n) ;
        cout << ans[0] ;
        for( i = 1 ; i < 10 ;i++ )
            printf(" %d",ans[i]) ;
        puts("") ;
    }
cout << "time: " << clock()-tt << endl;
    return 0 ;
}

0 0
原创粉丝点击