康托定理:
X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,其中a[i]为当前未出现的元素中是排在第几个(从0开始)。这就是康托展开。
#include<iostream> #include<cstring> #include<vector> #include<stdio.h> #include<algorithm> using namespace std; const int inf = 0x3f3f3f3f; int jiecheng[10]; int gcd(int a, int b) { return (b == 0 ? a : (gcd(b, a%b))); } void jc(int a) { jiecheng[0] = 1; for (int i = 1; i <= a; ++i) jiecheng[i] = i*jiecheng[i - 1]; } int main() { //freopen("in.txt", "r", stdin); vector<int>vec; int num; cin >> num; //输入数字的个数 jc(num - 1); int val; for (int i = 1; i <= num; ++i) { cin >> val; //输入每个数据 vec.push_back(val); } int cixu = 0; vector<int>arr(vec); sort(arr.begin(), arr.end()); int op = 0; while (!arr.empty()&&op<vec.size()) { int l = 0, r = num; while (l < r) { int mid = (l + r) >> 1; if (arr[mid]>vec[op]) r = mid - 1; else if (arr[mid] < vec[0]) l = mid + 1; else { arr.erase(arr.begin() + mid); l = mid; break; } } op++; cixu += jiecheng[--num] * l; } cout << cixu+1 << endl; //输出该数所在的序列 system("pause"); }
逆定理:
把一个大数拆成许多个位数,然后将这些个位数重新组合,使其形成一个新的数字,将这些数按从小到大排列,求第多少个数是多少?
#include<iostream> #include<cstring> #include<vector> #include<stdio.h> using namespace std; const int inf = 0x3f3f3f3f; int jiecheng[10]; int gcd(int a, int b) { return (b == 0 ? a : (gcd(b, a%b))); } void jc(int a) { jiecheng[0] = 1; for (int i = 1; i <= a; ++i) jiecheng[i] = i*jiecheng[i - 1]; } int main() { //freopen("in.txt", "r", stdin); vector<int>vec; int num; cin >> num; //输入数字的个数 jc(num - 1); int val; for (int i = 1; i <= num; ++i) { cin >> val; //输入每个数据的结果 vec.push_back(val); } int cixu; cin >> cixu; //输入要求次序 cixu--; int yushu = inf; while (yushu) { --num; yushu = cixu-cixu/jiecheng[num]*jiecheng[num]; cout << vec[cixu / jiecheng[num]] ; vec.erase(vec.begin() + cixu / jiecheng[num]); cixu = yushu; } while (!vec.empty()) { cout << vec[0] ; vec.erase(vec.begin()); } //system("pause"); }