1 求第k个排列
2 求给定排列在全排列中的序号
3 求下k个排列
#include <iostream> #include <stdlib.h> //#include <algorithm> #include <map> #include <time.h> using namespace std; unsigned int mp[1000+1] = {1, 1, 2, 6, 24, 120, 720}; unsigned int Fatorail(int n) { unsigned int value=1; if (mp[n]) return mp[n]; for (int i=1; i<=n; i++) value *= i; mp[n] = value; return value; } void reverse(int *p, int n) { int i=0, j=n-1; while (i<j) { swap(p[i], p[j]); i++, j--; } } /** @brief 给定一个排列p[s...e], 找出这样一个位置pos, 使得从pos开始的后面m为还剩下的排列数大于k */ int LeftPremutation(int *p, int s, int e, int kk, int &total) { int *t = new int[e-s+1]; int i,j; j=0; unsigned int sum=0; t[0] = p[e]; for (i=e-1; i>=s; i--) { int k; for (k=j; k>=0; k--) { //插入,保持有序 if (t[k]>p[i]) t[k+1] = t[k]; else break; } t[k+1] = p[i]; j++; //p[i]的前面有k个数字 k的后面有j-k-1个数字 if (j-k-1>0) sum += (j-k-1) * Fatorail(e-i); if (sum >= kk) { total = Fatorail(e-i+1); return i; } } total = sum; return -1; } /** @brief 求p[s...e]这个几个元素组成的第k个排列,结果存储在p[s...e]中 */ void PermutationByOrder(int *p, int s, int e, int k) { map<int, bool> flg; int i, j; //初始化所有元素都未被选中 for (i=s; i<=e; i++) flg[p[i]]=true; j=s; while (j<=e) { i=1; int t=Fatorail(e-j); //后面有e-j个数位 while ( (t*i)<k ) ++i; k -= (i-1)*t; int cnt=i; for (map<int, bool>::iterator iter=flg.begin(); iter!=flg.end() && cnt; iter++) { if (iter->second == true) cnt--; if (cnt==0) { flg[iter->first] = false; p[j++] = iter->first; break; } } } } /** @brief 生成1, 2, ... n, n个数构成的全排列中的k个排列 */ void PermutationByOrder(int *p, int n, int k) { //int values[] = {1, 1, 2, 6, 24, 120}; //n!的值 bool *flg = new bool[n+1]; //int *t = new int[n]; int i, j; for (i=0; i<=n; i++) flg[i] = true; j=0; while (j<n) { i=1; int t=Fatorail(n-j-1); while ((t*i)<k) i++; k -= (i-1)*t; int cnt=i; for (i=1; i<=n && cnt; i++) { if (flg[i]) cnt--; if (cnt==0) break; } p[j++] = i; flg[i] = false; } delete [] flg; } /** @brief 给定一个排列,返回它在全排列中的顺序 对于四位数的:如果第一位是4,即4xxx 那么说明第一位是1,2,3的排列已经列举过了。而1xxx总共有3!种。 2xxx, 3xxx也有3!种。规律就是: 4是第4个数,它的前面有3个数,那么先不 考虑后面,前面的排列至少为3*3!(3!:4的后面有3位数)。 接下来还要考虑后面的,类似的分析方法。 43xx:3*3!+2*2! 432x: 3*3!+2*2!+1 4321: 3*3!+2*2!+1+1 = 24 = 4! */ int OrderByPermutation(int *p, int n) { bool *flg = new bool[n+1]; int i, j; for (i=1; i<=n; i++) flg[i] = true; unsigned int sum=0; for ( i=0; i<n; i++) { int cnt=0; for (j=1; j<p[i]; j++) { if (flg[j]) cnt++; } flg[p[i]] = false; if (cnt) sum += Fatorail(n-i-1)*cnt; } return sum+1; } /* @brief 给定一个排列p[s...e],返回p[s...e]在由这e-s+1个元素构成的全排列中的序号 */ int OrderByPermutation(int *p, int s, int e) { map<int, bool> flg; int i, j; //初始化所有元素都未被选中 for (i=s; i<=e; i++) flg[p[i]]=true; j=s; unsigned int sum=0; while (j<e) { int cnt=0; //p[j]前面有cnt个数 for (map<int, bool>::iterator iter=flg.begin(); iter!=flg.end(); iter++) { if (iter->first==p[j]) break; if (flg[iter->first]==true) cnt++; } flg[p[j]] = false; if (cnt) sum += Fatorail(e-j)*cnt; j++; } return sum+1; } void Print(int *p, int n) { for (int i=0; i<n; i++) { if (i != n-1 ) cout << p[i] << " "; else cout << p[i] << endl; } } int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } int main() { int m; cin >> m; int i=0; while (i++<m) { int n, k; cin >> n >> k; int *p = new int[n]; int j=0; while (j<n) { cin >> p[j]; j++; } if (n<5 && k>=mp[n]) k %= mp[n]; int total; int oldk = k; while (1) { int k1=LeftPremutation(p, 0, n-1, k, total); if (k1==-1) { //升序排列 qsort(p, n, sizeof(int), cmp); //reverse(p, n); if (total) oldk -= (total+1); else oldk--; //oldk--; k=oldk; if (oldk == 0) { Print(p, n); break; } continue; } int k2=OrderByPermutation(p, k1, n-1); if (k2+oldk>total) { k = total+1; continue; } PermutationByOrder(p, k1, n-1, k2+oldk); Print(p, n); break; } delete [] p; } return 0; }