zoukankan      html  css  js  c++  java
  • 51nod 1042 数位dp

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042

    1042 数字0-9的数量

    基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
    收藏
    关注
    给出一段区间a-b,统计这个区间内0-9出现的次数。
    比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
    Input
    两个数a,b(1 <= a <= b <= 10^18)
    Output
    输出共10行,分别是0-9出现的次数
    Input示例
    10 19
    Output示例
    1
    11
    1
    1
    1
    1
    1
    1
    1
    1
    经典的数位dp题目,但是这个'0'真是搞得我恶心,第一次见是在玲珑某次比赛,那次一直怼这个最后爆零- -
    dp[i]表示[0,10
    i
    -1]之间所有的数里面0-9出现的次数,有dp[i]=10*dp[i-1]+pow(10,i-1),显然1-9的次数的一样的,0得话,
    因为没有以零开头的多位数,所以这里面是多计算了一部分'0'的,计算时遇到0就要想办法减去他才行。
    假如[0,999],多计算的就是100+10+1个零,对应的是001,002.....099,100是最高位,10是次高位,依次递推。
    假如要计算f(2049,0),第一次 s+=dp[3]*2;
    这两个dp[3]一个是加的 [0,999]一个是[1000,1999],但是我们只去掉一次就好了因为在[1000,1999]间那些零反而是我们需要的,就是这一点我糊涂好久。
     1 #include<cstring>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cmath>
     5 using namespace std;
     6 #define inf 0x3f3f3f3f
     7 #define LL  long long
     8 LL dp[25], zero[25] = { 0,0,10 };
     9 LL qpow(LL a,LL b,LL r=1){for(;b;b>>=1,a=a*a)if(b&1)r=r*a;return r;}
    10 void init()
    11 {
    12     dp[1]=1;
    13     for(LL i=2;i<19;++i)
    14         dp[i]=10*dp[i-1]+qpow(10,i-1);
    15 }
    16 LL f(LL N,LL digit)
    17 {
    18     if(N==0) {return digit?0:1;}
    19     int len=log(N+0.05)/log(10)+1;
    20     LL s=0,nx=N;
    21     for(int i=len;i>=1;--i)
    22     {
    23         LL mul=qpow(10,i-1);
    24         s+=dp[i-1]*(N/mul);
    25         {
    26         if(N/mul-1>=digit) s+=qpow(10,i-1);
    27         if(N/mul==digit) s+=N%mul+1;
    28         }
    29         N%=mul;
    30         //if(!digit) cout << "s=" << s << endl;
    31     }
    32     if (!digit)                                     //  删除前缀是0的结果
    33     {
    34         LL m = 1;
    35         while (nx)
    36         {
    37             s -= m;
    38             m *= 10;
    39             nx = nx / 10;
    40         }
    41     }
    42     //if (!digit) cout <<"s="<< s << endl;
    43     return s;
    44 }
    45 int main()
    46 {
    47     init();
    48     LL a,b,x;
    49     cin >> a >> b;
    50     for(x=0;x<=9;++x)
    51     {
    52         cout<<f(b,x)-f(a-1,x)<<endl;
    53     }
    54     return 0;
    55 }

        这是从新学习后自己写的代码

      

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long 
     4 LL f[25]={0,1};
     5 LL p10[25]={1,1};
     6 LL zero[25]={0,0};
     7 LL bit[25];
     8 void init(){
     9     for(int i=1;i<=20;++i) p10[i]=p10[i-1]*10;
    10     for(int i=2;i<=20;++i) zero[i]=zero[i-1]*10+10;
    11     for(int i=2;i<=20;++i) f[i]=f[i-1]*10+p10[i-1];
    12 }
    13 LL cal(LL N,int x){
    14     int len=0;
    15     while(N){
    16         bit[len++]=N%10;
    17         N/=10;
    18     }
    19     bit[len]=-1;
    20     LL ans=0,tot=0;
    21     for(int i=len-1;i>=0;--i){
    22         ans+=f[i]*bit[i];
    23         if(!x && i==len-1) ans-=(LL)(zero[i]);
    24         if(bit[i]>x && ((x==0&&i==len-1)==0) ) ans+=p10[i];
    25         ans+=p10[i]*bit[i]*tot;
    26         if(bit[i]==x) tot++;
    27     }
    28     return ans;
    29 }
    30 int main(){
    31     LL l,r,n,i,j,k;
    32     init();
    33     while(scanf("%lld%lld",&l,&r)==2){
    34         for(i=0;i<10;++i)
    35             printf("%lld
    ",cal(r+1,i)-cal(l,i));
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    Balanced Binary Tree
    Convert Sorted List to Binary Search Tree
    Convert Sorted Array to Binary Search Tree
    Binary Tree Zigzag Level Order Traversal
    Validate Binary Search Tree
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Maximum Depth of Binary Tree
    如何把U盘的两个盘或者多个盘合成一个
    bugku 想蹭网先解开密码
  • 原文地址:https://www.cnblogs.com/zzqc/p/7402907.html
Copyright © 2011-2022 走看看