zoukankan      html  css  js  c++  java
  • hdu2089不要62

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089

    回来再写,赶去大物实验。。

    -------------------------------------------------------------------------------

    刚开始学数位dp,简单说一下自己的理解。

    预处理部分先略过。。。

    下面是转移阶段:

    以n=84举例,看数位dp如何工作的。(针对本题,即求出不含4且不含62的数字个数)

    对第一位8:

      如果取0--7,则肯定满足小于n,有bit[4]=8种选择。

      再考虑后面一位,dp[1][2]表示含4或62的一位数的个数(只有一个4),ans+d[1][2]*bit[4]; {74,64,54,44,34,24,14,04}共8种

      因为8>4,所以第一位可能取到4,当取4时,后面一位不论取什么都可以(为了不与上面的情况重复,限制后面的不能含有4或62)

      dp[1][0]表示不含4或者62的一位数,即ans+=dp[i-1][0];    {40,41,42,43,45,46,47,48,49}共9种

      因为8>6,所以第一位取6时,第二位可以取2.  再加上 ans+=dp[i-1][1];  {62},共1种

    对第二位4, 所有情况均不满足,共0种。

    所以一共有8+9+1=18个含4或62的数字,从分析可以看出求的是<84的范围,不含84。

    好吧,我承认写的渣渣,,不过也理解了那么一丢丢

    总的来说,就是从高位往低位进行,每完成一位就把该位固定,继续下一位。

    分析每一位时都是从n向下取整(比如n=8000+,分析8时就是在分析0到7999),从而可以保证所有情况都小于n。

    分析完后,固定该位(如上固定为8,继续分析下一位时,其实就是在分析8000到n),刚好不重复不遗漏。

     再简单分析一个  8653  (下面加号意义自己理解)

    第一步:(0--7)+(000--999)

    第二步: 8+(0--5)+(00--99)

    第三步: 8+6+(0--4)+(0--9)

    第四步:8+6+5+(0-2)

    感觉这样写稍微好些。。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define ll long long
     4 int dp[11][3];
     5 int bit[11];
     6 int n,m;
     7 /*
     8 dp[i][0]  前i位没有不吉利数字
     9 dp[i][1]  前i位没有不吉利数字,但是第i位为2
    10 dp[i][2]  前i位有不吉利数字
    11 */
    12 void init()
    13 {
    14     memset(dp,0,sizeof(dp));
    15     dp[0][0]=1;
    16     for(int i=1;i<11;i++)
    17     {
    18         dp[i][0]=dp[i-1][0]*9-dp[i-1][1];
    19         dp[i][1]=dp[i-1][0];
    20         dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];
    21     }
    22 }
    23 int evil(int x)
    24 {
    25     int tmp=x;
    26     int ans=0;
    27     int len=0;
    28     while(x)
    29     {
    30         bit[++len]=x%10;
    31         x/=10;
    32     }
    33     bit[len+1]=0;
    34     int flag=0;
    35     for(int i=len;i;i--)
    36     {
    37         ans+=dp[i-1][2]*bit[i];
    38         if(flag) ans+=dp[i-1][0]*bit[i];
    39         else
    40             {
    41                 if(bit[i]>4) ans+=dp[i-1][0];
    42                 if(bit[i+1]==6&&bit[i]>2) ans+=dp[i][1];
    43                 if(bit[i]>6) ans+=dp[i-1][1];
    44             }
    45         if(bit[i+1]==6&&bit[i]==2||bit[i]==4) flag=1;
    46     }
    47     return tmp-ans;
    48 }
    49 int main()
    50 {
    51     init();
    52     while(scanf("%d%d",&n,&m)&&(n||m))
    53     {
    54         printf("%lld
    ",(ll)evil(m+1)-evil(n));
    55     }
    56 }
  • 相关阅读:
    LeetCode 623. Add One Row to Tree
    LeetCode 894. All Possible Full Binary Trees
    LeetCode 988. Smallest String Starting From Leaf
    LeetCode 979. Distribute Coins in Binary Tree
    LeetCode 814. Binary Tree Pruning
    LeetCode 951. Flip Equivalent Binary Trees
    LeetCode 426. Convert Binary Search Tree to Sorted Doubly Linked List
    LeetCode 889. Construct Binary Tree from Preorder and Postorder Traversal
    LeetCode 687. Longest Univalue Path
    LeetCode 428. Serialize and Deserialize N-ary Tree
  • 原文地址:https://www.cnblogs.com/yijiull/p/6634156.html
Copyright © 2011-2022 走看看