• SGU 258 Almost Lucky Numbers 接近幸运数(数位DP)


    题意:

      定义一个具有2n位的正整数,其前n位之和与后n位之和相等,则为lucky数。给定一个区间,问有多少个正数可以通过修改某一位数从而变成lucky数?注意不能含前导0。

    思路:

      我的想法是记录那些非lucky数,再想办法来统计,后来发现有点行不通,无法知道其前后部之和是否相等。如果记录lucky数,然后通过统计每个位上的数来变成lucky数,这更麻烦,因为会重复统计,比如11和22是lucky数,而21可以通过修改1位来变成lucky数,被统计了两次。

      学习了前辈的方法,也强迫一下自己别人的模板。据我对此模板的理解,第一次求解时是直接求解的,但是把所有统计过的都记录起来了,下次若还用到就直接返回就行了。复杂度是108吧。

      这是前辈们的代码,拿来理解一下,顺便适应一下新模板。

     1 #include <bits/stdc++.h>
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <map>
     7 #include <algorithm>
     8 #include <vector>
     9 #include <iostream>
    10 #define pii pair<int,int>
    11 #define INF 0x7f3f3f3f
    12 #define LL long long
    13 #define ULL unsigned long long
    14 using namespace std;
    15 const double PI  = acos(-1.0);
    16 const int N=10;
    17 const int M=45;
    18 const int mod=1e9+7;
    19 
    20 int f[N][N][99][N][N], bit[N+2];
    21 
    22 int dfs(int i,int up,int sum,int more,int less,bool e)    //e表示:是前缀?
    23 {
    24     if(i==0)
    25         return (sum!=M && ( sum+more>=M && sum-less<=M ) );
    26 
    27     if(!e && ~f[i][up][sum][more][less])   //已经计算好了(非前缀才行)
    28         return f[i][up][sum][more][less];
    29 
    30     int ans=0;
    31     int d= i==up? 1: 0;        //起始,注意首位不能为0啊
    32     int u= e? bit[i]: 9;       //终止,注意末位不能超啊
    33     for( ; d<=u; d++)          //是否为最后一个取决于参数e
    34     {
    35         int ssum=  i>(up>>1)? sum+d: sum-d; //单峰形的
    36         int mmore= i>(up>>1)? max(more, 9-d): max(more, d);   //前部:可加。后部:可减
    37         int lless= i>(up>>1)? max(less, i==up?d-1:d): max(less, 9-d);//前部:可减。后部:可加
    38         ans+=dfs(i-1,up, ssum, mmore, lless, e&&d==u);
    39     }
    40     return e? ans: f[i][up][sum][more][less]=ans; //前缀的返回不同
    41 }
    42 
    43 
    44 int cal(int n)
    45 {
    46     if(n<10)    return 0;   //仅个位数不可能是lucky数
    47     int len=0, ans=0;
    48     while(n)    //拆数
    49     {
    50         bit[++len]=n%10;
    51         n/=10;
    52     }
    53 
    54     for(int i=2; i<=len; i+=2)      //i是数的长度
    55         ans+=dfs(i,i,0+M,0,0,i==len);
    56     return ans;
    57 }
    58 
    59 int main()
    60 {
    61     //freopen("input.txt","r",stdin);
    62     memset(f,-1,sizeof(f));
    63     int L, R;
    64     while( ~scanf("%d%d",&L,&R) )
    65         printf("%d
    ", cal(R)-cal(L-1) );
    66     return 0;
    67 }
    AC代码
  • 相关阅读:
    PHP实现无限极分类
    html2canvas生成并下载图片
    一次线上问题引发的过程回顾和思考,以更换两台服务器结束
    Intellij IDEA启动项目报Command line is too long. Shorten command line for XXXApplication or also for
    mq 消费消息 与发送消息传参问题
    idea 创建不了 java 文件
    Java switch 中如何使用枚举?
    Collections排序
    在idea 设置 git 的用户名
    mongodb添加字段和创建自增主键
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4853962.html
Copyright © 2020-2023  润新知