zoukankan      html  css  js  c++  java
  • 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代码
  • 相关阅读:
    sublime显示当前文件的编码格式
    关于jquery中html()、text()、val()的区别
    bit,Byte,B,KB,MB,GB
    python之序列操作
    编程常用密匙
    js数组操作
    ob函数的使用
    php使用zlib实现gzip压缩
    js兼容性汇总
    centos7下源码编译安装mysql5.7
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4853962.html
Copyright © 2011-2022 走看看