zoukankan      html  css  js  c++  java
  • Enum:Backward Digit Sums(POJ 3187)

                      

                     反过来推

      题目大意:就是农夫和这只牛又杠上了(怎么老是牛啊,能换点花样吗),给出一行数(从1到N),按杨辉三角的形式叠加到最后,可以得到一个数,现在反过来问你,如果我给你这个数,你找出一开始的序列(可能存在多个序列,输出字典序最小的那个)。

      这一题首先你要看懂原文的那个1到N是什么意思,就是那一行数只能是1到N,而不是1到10(我一开始犯了这个愚蠢的错误,导致枚举到风扇呼呼的转),如果是这样给你,那么这道题就很简单啦,就直接是用next_permutation枚举所有的序列就可以了,然后找出字典序最小的那个。

      但是这里有个问题,如果你真的找出一个然后去比较字典序,那真是太慢了,一开始直接暴力枚举+测试一个一个字串的速度

      

      看到了没?差点就超时了,这个还是我直接用二维数组+迭代的,换暴力DFS直接就超时了吧。

      其实这个时候我们可以看到,这样做我们忽略了一个事实,如果字串是顺序的,我们可以回想一下我们的枚举是怎枚举的(STL里面也是这么写的),是一个循环从1到N,然后找到没有被标记的数,然后进去递归,这样的话,其实就隐含了字典序排序了,如果我们一开始按照12345678...这样排列下来,那么找到的第一个字串,肯定是字典序最小的,所以,我们找到之后直接break就可以了

      

     1 #include <iostream>
     2 #include <functional>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 static int set[11], tmp[11];
     8 static int sum, length;
     9 
    10 void enum_string(const int,const int);
    11 bool scmop(void);
    12 
    13 int main(void)
    14 {
    15     while (~scanf("%d%d", &length, &sum))
    16     {
    17         for (int i = 1; i <= length; i++)
    18             tmp[i - 1] = i;
    19         if (length == 1 && tmp[0] == sum)
    20         {
    21             for (int i = 0; i < length; i++)
    22                 printf("%d ", tmp[i]);
    23             printf("
    ");
    24             continue;
    25         }
    26         do{
    27             for (int i = 0; i < length - 1; i++)
    28                 set[i] = tmp[i] + tmp[i + 1];
    29             for (int i = length - 2; i >= 0; i--)
    30             {
    31                 for (int j = 0; j < i; j++)
    32                     set[j] = set[j] + set[j + 1];
    33             }
    34             if (set[0] == sum)
    35             {
    36                 for (int i = 0; i < length; i++)
    37                     printf("%d ", tmp[i]);
    38                 printf("
    ");
    39                 break;
    40             }
    41         } while (next_permutation(tmp, tmp + length));
    42 
    43     }
    44     return 0;
    45 }

        

      还没完,开始我不是说了吗?这一题是按照杨辉三角的形式展开的,我们知道杨辉三角的每一行的数都是组合数Ckn,那么在数学上,杨辉三角的加法一行数的相加次数相当于这个Ckn,

        

        也就是说,我们只用把这一行的数乘以Ckn就可以得到结果了,这样做会更快

      

     1 #include <iostream>
     2 #include <functional>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 static int set_sum, tmp[11], Cn[11];
     8 static int sum, length;
     9 
    10 void Cal_Cn(const int);
    11 
    12 int main(void)
    13 {
    14     while (~scanf("%d%d", &length, &sum))
    15     {
    16         for (int i = 1; i <= length; i++)
    17             tmp[i - 1] = i;
    18         memset(Cn, 0, sizeof(Cn));
    19         Cal_Cn(length);
    20         if (length == 1 && tmp[0] == sum)
    21         {
    22             for (int i = 0; i < length; i++)
    23                 printf("%d ", tmp[i]);
    24             printf("
    ");
    25             continue;
    26         }
    27         do{
    28             set_sum = 0;
    29             for (int i = 0; i < length; i++)
    30                 set_sum += Cn[i] * tmp[i];
    31             if (set_sum == sum)
    32             {
    33                 for (int i = 0; i < length; i++)
    34                     printf("%d ", tmp[i]);
    35                 printf("
    ");
    36                 break;
    37             }
    38         } while (next_permutation(tmp, tmp + length));
    39     }
    40     return 0;
    41 }
    42 
    43 void Cal_Cn(const int length)
    44 {
    45     Cn[0] = 1;
    46     for (int j = 1; j < length; j++)
    47     {
    48         Cn[j] = length - 1;
    49         for (int k = 2; k <= j; k++)
    50             Cn[j] *= (length - k);
    51         for (int k = 1; k <= j; k++)
    52             Cn[j] /= k;
    53     }
    54 }

      

      最后,32ms

  • 相关阅读:
    从员工到总监,你要明白的8个道理!
    IT民工2013的升迁
    你会对老板说这十句傻话吗
    BIO
    同步工具类
    NIO(一)
    Lock与Condition
    forkJoin
    线程池与Future
    今天需要获取一个网站的web服务反馈回来的数据,找到份不错的帖子关于WebClient类的使用,记录下来·
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4854761.html
Copyright © 2011-2022 走看看