组合数学(全排列)+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函数

 

你可能感兴趣的:(Graph)