zoukankan      html  css  js  c++  java
  • hdu 5676 ztr loves lucky numbers(dfs+离线)

    Problem Description
    ztr loves lucky numbers. Everybody knows that positive integers are lucky if their decimal representation doesn't contain digits other than 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.
    
    Lucky number is super lucky if it's decimal representation contains equal amount of digits 4 and 7. For example, numbers 47, 7744, 474477 are super lucky and 4, 744, 467 are not.
    
    One day ztr came across a positive integer n. Help him to find the least super lucky number which is not less than n.
     
    Input
    There are T(1≤n≤105) cases
    
    For each cases:
    
    The only line contains a positive integer n(1≤n≤1018). This number doesn't have leading zeroes.
     
    Output
    For each cases
    Output the answer
     
    Sample Input
    2
    4500
    47
    Sample Output
    4747 
    47

    直接暴力显然TLE,考虑按位DFS

    每一位只可能是4或7

    所以根据这个来DFS即可,时间复杂度O(T*2^{log_{10}n})O(T2log10​​n​​)

    考虑到T特别大,不可能每次都DFS

    而经过计算,2^{18}=262144218​​=262144,所以全部储存下来

    对于每次询问,二分即可

    考虑一个边界条件,即当结果爆ll怎么办?

    即答案应当为10个4、10个7的时候,显然unsigned long long也不行

    那么只能采用特判了

    首先,由于每一位只能是4或7,且
    2^{18}=262144218​​=262144,故而考虑离线打表,即利用dfs求解出所有只含数字4和7,且4和7数量相等的数
    1 void dfs(ll sum,int c1,int c2){
    2    if(c1>=k1 && c2>=k2){
    3       ans[num++]=sum;
    4       return;
    5    }
    6    if(c1<k1) dfs(sum*10+4,c1+1,c2);
    7    if(c2<k2) dfs(sum*10+7,c1,c2+1);
    8 }

    结果存储在ans数组中,此时可以得到符合条件的数有66196+1个,而数据有T组,好吧,那就二分查找

     1 int cnt = lower_bound(ans,ans+num,n)-ans; 

    需要注意的一点是,当n>777777777444444444的时候,18位数里面已经没有比这更大的符合条件的数了,那么只能特判一下,解为最小的20位符合条件的数,即44444444447777777777

    AC代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 #define ll long long
     6 #define N 1000000
     7 int k1,k2;
     8 ll ans[N];
     9 int num;
    10 ll n;
    11 void dfs(ll sum,int c1,int c2){
    12    if(c1>=k1 && c2>=k2){
    13       ans[num++]=sum;
    14       return;
    15    }
    16    if(c1<k1) dfs(sum*10+4,c1+1,c2);
    17    if(c2<k2) dfs(sum*10+7,c1,c2+1);
    18 }
    19 void init(){
    20    num=0;
    21    for(int i=2;i<=18;i+=2){
    22       k1=k2=i/2;
    23       dfs(0,0,0);
    24    }
    25 }
    26 int main()
    27 {
    28     init();
    29     int t;
    30     scanf("%d",&t);
    31     while(t--){
    32         scanf("%I64d",&n);
    33         int cnt = lower_bound(ans,ans+num,n)-ans;
    34         if(cnt<num){
    35            printf("%I64d
    ",ans[cnt]);
    36         }else{
    37            printf("44444444447777777777
    ");
    38         }
    39     }
    40     return 0;
    41 }
  • 相关阅读:
    Spring第一次测试错题解析
    正则回顾
    Spring经典---AOP
    动态代理
    MyBatis第一次测试卷---错题分析
    JS中对数组元素进行增删改移
    限制条件补全代码系列题
    字符串去空格
    数组去重
    数组排序
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/5452889.html
Copyright © 2011-2022 走看看