zoukankan      html  css  js  c++  java
  • CodeForces

    题目链接:http://codeforces.com/problemset/problem/95/B

    题意:

      给你一个数字,要你求出不小于它的最小的超级完美数。超级完美数的定义是:这个数字每一位都是4或者7,并且4的总位数要等于7的总位数。

    思路:

      我刚开始推算的思路是:要是这个数有奇数位,那么就只需要加一位,加了一个位数的话肯定是比原来的数要大的,就只需要求出加了一位之后的最小超级完美数,即前一半位数是4,后一半位数是7。如果是偶数位的话,先将这个数与当前位数的最大的超级完美数比较,即前一半7后一半4的那个数,如果这个数比当前位最大的超级完美数还要大,说明还要加两位,加位的答案就是前一半4后一半7。否则的话,就从当前位数最小的超级完美数开始遍历,找出最小的不小于它的超级完美数。(事实证明,前面的想法都是没问题的,问题就出在这里)因为超级完美数都是相等数量的4和相等数量的7组成的,所以我就想着字典序全排列的话,从小到大遍历过去判断就行了,但是这样子做是会超时的,因为字典序全排列这个过程时间消耗很大。改进的方法就是,不依次与超级完美数进行比较,而是直接处理当前这个数,将它变成符合要求的超级完美数。然后看了下别人写的,感觉这个dfs的写法挺好的,避免了我之前的一些重复操作。下面就给出我自己的TLE代码和别人用dfs写的AC代码吧。

    代码:

     1 /*————————————————————AC代码————————————————————*/
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn = 1e5 + 10;
     6 int len;
     7 char str[maxn];
     8 char ans[maxn];
     9 bool dfs(int pos, int sum1, int sum2, bool flag)    //pos指当前位数,sum1指4的总个数,sum2指7的总个数,flag标识符
    10 {
    11     if(pos >= len)
    12         return true;
    13     if(flag)    //前面有位数变大了,那么后面的数就按一半4一半7排列
    14     {
    15         for(int i = 0; i < sum1; i++)
    16             ans[pos++] = '4';
    17         for(int i = 0; i < sum2; i++)
    18             ans[pos++] = '7';
    19         return true;
    20     }
    21     if(sum1 && str[pos] <= '4')
    22     {
    23         if(dfs(pos + 1, sum1 - 1, sum2, str[pos] != '4'))    //遍历到一个比4小的数,并且将这个位数的数变成4是可行的
    24         {
    25             ans[pos] = '4';
    26             return true;
    27         }
    28     }
    29     if(sum2 && str[pos] <= '7')
    30     {
    31         if(dfs(pos + 1, sum1, sum2 - 1, str[pos] != '7'))    //遍历到一个比7小的数,并且将这个位数的数变成7是可行的
    32         {
    33             ans[pos] = '7';
    34             return true;
    35         }
    36     }
    37     return false;    //没有比4和7小的数,说明当前位数不够,要加两位
    38 }
    39 
    40 int main()
    41 {
    42     cin >> str;
    43     len = strlen(str);
    44     if(len & 1 || !dfs(0, len / 2, len / 2, 0))
    45     {
    46         if(len & 1)        //奇数位加一位
    47             len++;
    48         else    //dfs返回false加两位
    49             len += 2;
    50         //加位的话一半4一半7就行
    51         int i;
    52         for(i = 0; i < len / 2; i++)
    53             ans[i] = '4';
    54         for(i ; i < len; i++)
    55             ans[i] = '7';
    56     }
    57     cout << ans << endl;
    58     return 0;
    59 }
     1 /*————————————————————TLE代码————————————————————*/
     2 #include<stdio.h>
     3 #include<stdlib.h>
     4 #include<algorithm>
     5 #include<cstring>
     6 
     7 const int maxn = 1e5 + 10;
     8 char num[maxn];
     9 char tmp[maxn];
    10 
    11 int main()
    12 {
    13     while(scanf("%s", num) != EOF)
    14     {
    15         int len = strlen(num);
    16         if(len % 2)    //奇数位的话,+1位,前一半是4,后一半是7
    17         {
    18             for(int i = 0; i < (len + 1) / 2; i++)
    19             {
    20                 printf("4");
    21             }
    22             for(int i = (len + 1) / 2; i < len + 1; i++)
    23             {
    24                 printf("7");
    25             }
    26             printf("
    ");
    27         }
    28         else
    29         {
    30             for(int i = 0; i < (len / 2); i++)
    31             {
    32                 tmp[i] = '7';
    33             }
    34             for(int i = (len / 2); i < len; i++)
    35             {
    36                 tmp[i] = '4';
    37             }
    38             //如果比当前位数情况下最大的超级完美数还要大,就要加两位
    39             if(strcmp(num, tmp) == 1)
    40             {
    41                 //加位前一半4,后一半7
    42                 for(int i = 0; i < ((len + 2) / 2); i++)
    43                 {
    44                     printf("4");
    45                 }
    46                 for(int i = ((len + 2) / 2); i < len + 2; i++)
    47                 {
    48                     printf("7");
    49                 }
    50                 printf("
    ");
    51             }
    52             else
    53             {
    54                 //位数固定,4和7的数量固定,字典序全排列列举比较,找最小的不低于的,就从最小的开始
    55                 for(int i = 0; i < (len / 2); i++)
    56                 {
    57                     tmp[i] = '4';
    58                 }
    59                 for(int i = (len / 2); i < len; i++)
    60                 {
    61                     tmp[i] = '7';
    62                 }
    63                 if(strcmp(num, tmp) != 1)
    64                 {
    65                     for(int i = 0; i < len; i++)
    66                         printf("%c", tmp[i]);
    67                     printf("
    ");
    68                 }
    69                 else
    70                 {
    71                     while(std::next_permutation(tmp, tmp + len))
    72                     {
    73                         if(strcmp(num, tmp) != 1)
    74                         {
    75                             for(int i = 0; i < len; i++)
    76                                 printf("%c", tmp[i]);
    77                             printf("
    ");
    78                             break;
    79                         }
    80                     }
    81                 }
    82             }
    83         }
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    Method of Four Russians 学习笔记
    一道不知道哪里来的数论题
    ICPC2021银川 游记
    决策单调性优化dp学习笔记
    浅谈如何优美地实现线段树?
    2021 EC Final 2020 题解
    5.5 SYSU校内训练
    5.4 SYSU校内训练
    存储相关招聘信息-长期
    screen几个使用方法
  • 原文地址:https://www.cnblogs.com/friend-A/p/9436763.html
Copyright © 2011-2022 走看看