zoukankan      html  css  js  c++  java
  • 组合数学(全排列)+DFS CSU 1563 Lexicography

    题目传送门

     1 /*
     2     题意:求第K个全排列
     3     组合数学:首先,使用next_permutation 函数会超时,思路应该转变,
     4     摘抄网上的解法如下:
     5         假设第一位是a,不论a是什么数,axxxxxxxx一共有8!种选择。 
     6         297192 div 8! = 7,余14952,所以第一位是1-9中的第8个数,也就是8。 
     7         14952 div 7! = 2,余4872,所以第二位是3。 
     8         4872 div 6! = 6,余552,所以是第三位是1245679这七个数中的第7个,也就是 9。 
     9         552 div 5! = 4,余72,所以是124567中的第5个,也就是6。 
    10         72 div 4! = 2,余24,所以是4。 
    11         这时候就不用算了,因为24 = 4!,而剩下的数就是1257这4个,他们组成的排列的第 
    12         24个必然是7521。
    13     以上解法只符合没有重复的序列,但是思路一致,把除法改为减法,每一次更新之后的全排列的数量
    14     即 Ann / Amm 的个数,可以用DFS实现
    15 */
    16 #include <cstdio>
    17 #include <iostream>
    18 #include <algorithm>
    19 #include <stack>
    20 #include <cmath>
    21 #include <cstring>
    22 #include <vector>
    23 using namespace std;
    24 
    25 const int MAXN = 1e4 + 10;
    26 const int INF = 0x3f3f3f3f;
    27 char s[20];
    28 int cnt[30];
    29 int pos[20];
    30 int len;
    31 
    32 long long fact(int x)
    33 {
    34     long long res = 1;
    35     for (int i=1; i<=x; ++i)    res *= i;
    36 
    37     return res;
    38 }
    39 
    40 long long f(int step)
    41 {
    42     long long res = fact (step);
    43     for (int i=0; i<26; ++i)    if (cnt[i])    res /= fact (cnt[i]);
    44 
    45     return res;    
    46 }
    47 
    48 void DFS(int step, long long k)
    49 {
    50     if (step == len)
    51     {
    52         for (int i=0; i<len; ++i)    printf ("%c", 'A' + pos[i]);
    53         puts ("");    return ;
    54     }
    55 
    56     for (int i=0; i<26; ++i)
    57     {
    58         if (cnt[i] == 0)    continue;
    59         cnt[i]--;
    60         long long tmp = f (len - step - 1);
    61         if (tmp < k)    {k -= tmp;    cnt[i]++;}
    62         else
    63         {
    64             pos[step] = i;
    65             DFS (step+1, k);
    66             return ;
    67         }
    68     }
    69 }
    70 
    71 int main(void)        //CSU 1563 Lexicography
    72 {
    73     //freopen ("C.in", "r", stdin);
    74 
    75     long long k;
    76     while (scanf ("%s%lld", &s, &k) == 2)
    77     {
    78         if (s[0] == '#' && k == 0)    break;
    79 
    80         len = strlen (s);
    81         memset (pos, 0, sizeof (pos));
    82         memset (cnt, 0, sizeof (cnt));
    83         for (int i=0; i<len; ++i)    cnt[s[i]-'A']++;
    84 
    85         DFS (0, k);
    86     }
    87 
    88     return 0;
    89 }
    90 
    91 /*
    92 MAC
    93 PICC
    94 IGNORE
    95 */

    附带给出求1~9无重复数字的第K个全排列的两种方法

     1 /*
     2     假设第一位是a,不论a是什么数,axxxxxxxx一共有8!种选择。 
     3     297192 div 8! = 7,余14952,所以第一位是1-9中的第8个数,也就是8。 
     4     14952 div 7! = 2,余4872,所以第二位是3。 
     5     4872 div 6! = 6,余552,所以是第三位是1245679这七个数中的第7个,也就是 9。 
     6     552 div 5! = 4,余72,所以是124567中的第5个,也就是6。 
     7     72 div 4! = 2,余24,所以是4。 
     8     这时候就不用算了,因为24 = 4!,而剩下的数就是1257这4个,他们组成的排列的第 
     9     24个必然是7521。 
    10 */
    11 #include <cstdio>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <stack>
    15 #include <cmath>
    16 #include <cstring>
    17 #include <vector>
    18 using namespace std;
    19 
    20 const int MAXN = 1e4 + 10;
    21 const int INF = 0x3f3f3f3f;
    22 int num[11];
    23 int ans[11];
    24 int f[11];
    25 
    26 int main(void)
    27 {
    28     //freopen ("test_C.in", "r", stdin);
    29 
    30     int k;
    31     while (scanf ("%d", &k) == 1)
    32     {
    33         f[0] = 1;
    34         for (int i=1; i<=9; ++i)    {f[i] = f[i-1] * i;    num[i] = i;}
    35 
    36         int tot = 0;
    37         int len = 9;
    38         bool flag = false;
    39         while (tot < len)
    40         {
    41             int pos = k / f[len-tot-1] + 1;
    42             k %= f[len-tot-1];
    43 
    44             if (k == 0)    {pos--;    flag = true;}
    45 
    46             int t = 0;
    47             for (int i=1; i<=9; ++i)
    48             {
    49                 if (num[i] != 0)
    50                 {
    51                     ++t;
    52                     if (t == pos)
    53                     {
    54                         printf ("%d", num[i]);
    55                         tot++;    num[i] = 0;    break;
    56                     }
    57                 }
    58             }
    59 
    60             if (flag)
    61             {
    62                 for (int i=9; i>=1; --i)
    63                 {
    64                     if (num[i] != 0)    printf ("%d", num[i]);
    65                 }
    66                 break;
    67             }
    68         }
    69         puts ("");
    70     }
    71     return 0;
    72 }
    73 
    74 /*
    75 839647521
    76 */
    1. 用上面的思路
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <stack>
     5 #include <cmath>
     6 #include <cstring>
     7 #include <vector>
     8 using namespace std;
     9 
    10 const int MAXN = 1e4 + 10;
    11 const int INF = 0x3f3f3f3f;
    12 int num[11];
    13 int ans[11];
    14 int f[11];
    15 
    16 int main(void)
    17 {
    18     //freopen ("test_C.in", "r", stdin);
    19 
    20     int k;
    21     while (scanf ("%d", &k) == 1)
    22     {
    23         for (int i=1; i<=9; ++i)    num[i] = i;
    24 
    25         int len = 9;
    26         long long cnt = 0;
    27         do{
    28             ++cnt;
    29             if (cnt == k)    break;
    30         }while (next_permutation (num+1, num+1+len));
    31 
    32         for (int i=1; i<=9; ++i)
    33             printf ("%d", num[i]);
    34         puts ("");
    35     }
    36     return 0;
    37 }
    38 
    39 /*
    40 839647521
    41 */
    2. 用next_permutation函数
    编译人生,运行世界!
  • 相关阅读:
    Linux shell脚本基础学习详细介绍(完整版)二
    python读取单个文件操作
    【转载】HTTP 缓存的四种风味与缓存策略
    【转载】HTTP 响应头与状态码
    【转载】HTTP 请求头与请求体
    【转载】HTTP 基础与变迁
    3-2 从单词中获取单词出现的频率信息,并把他们写进对应的列表里
    170925_2 Python socket 创建UDP的服务器端和客户端
    170925_1 Python socket 创建TCP的服务器端和客户端
    2-2 列表推导同 filter 和 map 的比较
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4444286.html
Copyright © 2011-2022 走看看