zznu 1255 数字统计(数位DP, 数学方法)

最近在学数位DP, 感觉还是满有收获的! 做了几个题之后想起来自己OJ上曾经做的一道题,以前是用数学方法写的,现在改用数位DP来写了一遍。

题目:

1255: 数字统计

时间限制: 1 Sec  内存限制: 128 MB
提交: 31  解决: 4
[提交][状态]

题目描述

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

输入

给出表示书的总页码的整数n(1≤n≤2^31-1)

输出

输出10行,在第k行输出页码中用到数字k-1 的次数,k=1,2,…,10。

样例输入

11

样例输出

1

4

1

1

1

1

1

1

1

1

 

链接:http://acm.zznu.edu.cn/problem.php?id=1255

数学方法:

其实就是假设每一位是0-9然后进行判断, 计算出结果

#include<stdio.h>

int  Slove(int num,int k)

{

    int L, R, M, P = 1, a = num;

    int sum = 0;

    while(a)

    {

        R = num%P;

        M = a%10;

        L = a/10;

        if(k)

        {

            if(k < M)

                sum += (L+1)*P;

            else if(k == M)

                sum += L*P + (R+1);

            else

                sum += L*P;

        }

        else

        {

            if(a<10)

                break;

            if(k == M)

                sum += (L-1)*P + (R+1);

            else

                sum += L*P;

        }

        P *= 10;

        a /= 10;



    }

    return sum;

}



int main()

{

    int  n, ans;

    int i;

    scanf("%d",&n);

    for(i=0; i<=9; i++)

    {

        ans = Slove(n,i);

        printf("%d\n",ans);

    }

    return 0;

}

数位DP;

这个就比较通用了, 就是套模版, 对数据的处理上 稍加注意, 然后把状态确定好。

 

#include<cstdio>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<cmath>

using namespace std;

typedef long long LL;

LL dp[20][20][11][2];//dp[位数][数字出现的次数][这个数字是多少][首位是否是0]

int bit[20];



LL dfs(int pos,int cou,int num,int flag,bool is0)

{

    if( pos == -1 )

    {

        return  cou;

    }

    

    if(!flag && dp[pos][cou][num][is0] != -1)

        return dp[pos][cou][num][is0];

    

    LL ans = 0;

    int end = flag? bit[pos]: 9;



    for(int i=0; i<=end; i++)

    {

        if(i == num && !(is0 && i == 0) )

            ans += dfs(pos-1, cou+1, num, flag && i == end,  is0 && i == 0 );

        else

            ans += dfs(pos-1, cou, num, flag && i == end, is0 && i == 0 );

    }

    

    if(!flag)

        dp[pos][cou][num][is0] = ans;

    

    return ans;

}





void solve(LL n)

{

    int len = 0, i, m = n;

    LL ans;

    while(n)

    {

        bit[len++] = n%10;

        n /= 10;

    }

    

    for(i=0; i<=9; i++)

    {

        ans = dfs(len-1, 0, i, 1, 1);

        printf("%lld\n", ans);

    }

//    printf("\n\n\n");

}



int main()

{

    LL a;

    memset(dp, -1 ,sizeof(dp));

    

    while(scanf("%lld", &a) != EOF)

    {

        solve(a);

    }

//    printf("\n\n\n");

    return 0;

}

 

你可能感兴趣的:(方法)