• HDU 5787 K-wolf Number


    题目:K-wolf Number

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5787

    题意:给出L,R,K,求L到R之间有多少数满足:(10进制下)任意两个相等的数字至少相差K位。(1<=L<=R<=1e18,2<=k<=5)。

    思路:

      dp[i][j]:表示i 位且前面k位数为j 的情况有多少种,为了细节处理方便,dp数组形式改为:dp[pos][p1][p2][p3][p4]表示pos位,p1、p2、p3、p4是前面四位数字。初始化为10、10、10、10表示前导0。

      采取记忆化搜索的姿势,dfs(pos,p1,p2,p3,p4,flag),flag=1表示这一位数有限制(不是题目要求中的限制,而是比如1234,那么第一位确定为1时,第二位最高只能2的限制。)具体在代码解释。

      有点坑的是我尝试用dp[pos][pre]形式解的时候,第二维不能是1万,应该要10万,不然pre%1000*10+i,原本的1023会变成023i,会被误认为23i,就少判断了一个是否等于0。

    AC代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 typedef long long LL;
     4 LL dp[20][11][11][11][11];
     5 int bt[20],bo;
     6 LL L,R;
     7 int K;
     8 bool check(int p1,int p2,int p3,int p4,int now)  //根据K进行判断i是否可以和p1、p2、p3、p4共存
     9 {
    10   if(K==2) return now!=p4;
    11   else if(K==3) return now!=p3 && now!=p4;
    12   else if(K==4) return now!=p2 && now!=p3 && now!=p4;
    13   else return now!=p1 && now!=p2 && now!=p3 && now!=p4;
    14 }
    15 LL dfs(int pos,int p1,int p2,int p3,int p4,bool flag)
    16 {
    17   if(pos==-1) return p4!=10;  //结束判断,如果p4还等于10,那说明全是0,在这里,我规定0不满足条件。
    18   if(!flag && dp[pos][p1][p2][p3][p4]!=-1) return dp[pos][p1][p2][p3][p4];  //如果以前存过值,直接取。
    19   // 存取值都在flag=0的情况下进行,也就是接下来pos位无限制(只有题目限制)的条件下进行。
    20   int limit= flag?bt[pos]:9;  //limit表示这一位最高可以取到多少,没有限制就是9,有限制就是原数的这一位数字
    21   LL ret=0;
    22   for(int i=0;i<=limit;i++)
    23   {
    24     //如果p4还等于10表示前面全是前导0,i又取0,那么pos位还是前导0。
    25     if(i==0 && p4==10) ret+=dfs(pos-1,p1,p2,p3,10,flag && i==limit);
    26     else if(check(p1,p2,p3,p4,i)) ret+=dfs(pos-1,p2,p3,p4,i,flag && i==limit); //判断i是否可以和前面的数字共存。
    27   }
    28   if(!flag) dp[pos][p1][p2][p3][p4]=ret; //存值
    29   return ret;
    30 }
    31 LL solve(LL x)
    32 {
    33   if(x<=0) return 0;
    34   bo=0;
    35   while(x)
    36   {
    37     bt[bo++]=x%10;
    38     x/=10;
    39   }
    40   return dfs(bo-1,10,10,10,10,1);
    41 }
    42 int main()
    43 {
    44   while(scanf("%I64d%I64d%d",&L,&R,&K)!=EOF)
    45   {
    46     memset(dp,-1,sizeof(dp));
    47     printf("%I64d
    ",solve(R)-solve(L-1));
    48   }
    49   return 0;
    50 }
  • 相关阅读:
    SVN 权限配置详解
    sql插件,SQLPrompt
    SQL Server 复制表及数据的两种方法
    windows如何查看某个端口被谁占用
    (3)FluidMoveBehavior 之模仿 Windows Phone 开始菜单的 Tile 长按后排序
    (2)FluidMoveBehavior 之单击 Grid 中 Tile 进行排序
    (1)FluidMoveBehavior 之 ListBox 中详细内容项飞出来
    03、Windows Phone 套接字(Socket)实战之WP客户端设计
    02、Windows Phone 套接字(Socket)实战之服务器端设计
    01、Windows Phone 套接字(Socket)实战之交互设计
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5734961.html
Copyright © 2020-2023  润新知