您的位置:首页 > 编程语言 > C语言/C++

康托展开和逆康托

2017-03-27 21:05 239 查看
彻底搞懂康托和逆康托

康拓展开

康托展开表示的是当前排列在n个不同元素的全排列中的名次

ans = an*(n-1)! + an-1 * (n-2)! + …+ a2 * 1! + a1 * 0!

其中表示第i个元素在未出现的元素中排列第几。

举个简单的例子:

对于排列4213来说,

(1)4在4213中排第3,注意从0开始,

(2)2在213中排第1,

(3)1在13中排第0,

(4)3在3中排第0,即:

这样得到4213在所有排列中排第ans=20(除第一个以外,比如1234这个排列,第20个是4132,第21个才是4213)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 18;
ll f[maxn];
void init()
{
ll sum = 1;
for (ll i = 1; i <= 18; i++) {
sum *= i;
f[i] = sum;
}
}

ll Work(string str)
{
int len = str.length();
ll ans = 0;
for (int i = 0; i < len; i++)
{
int tmp = 0;
for (int j = i+1; j < len; j++)
{
if (str[j] < str[i]) tmp++;
}
ans +=  tmp*f[len-i-1];
}
return ans;
}
int main()
{
init();
string s = "bckfqlajhemgiodnp";
cout << Work(s) << endl;
return 0;
}

//22952601027516


还有就是逆康托:

 例 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕

找出第96个数

  (1)首先用96-1得到95

  (2)用95去除4! 得到3余23

  (3)用23去除3! 得到3余5

  (4)用5去除2!得到2余1

  (5)用1去除1!得到1余0

计算:

(1)有3个数比它小的数是4,所以第一位是4

(2)有3个数比它小的数是4但4已经在之前出现过了,所以是5(因为4在之前出现过了所以实际比5小的数是3个)

(3)有2个数比它小的数,是3

(4)有1个数比它小的数,是2

(5)最后一个数只能是1

所以这个数是45321

那如果一个原始数是字符串,或者大整数呢,

下面考虑了long long 范围内也就是字符串18内及以内的数的排列查找第几个数。

比如传入m = 1234, n = 16,那这个结果就是3241,

比如传入字符串m =“abcdefghijklmnopq”, n = 22952601027517,

那这个结果就是”bckfqlajhemgiodnp”,也就是它的第22952601027517排列数是”bckfqlajhemgiodnp”。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//     12345
ll f[6];
void init(string m)
{
ll sum = 1;
for (ll i = 1; i <= m.length(); i++)
{
sum *= i;
f[i] = sum;
}
}
void Work(string m, ll n)
{
n--;
vector<char> v;
vector<char> result;
for (ll i = 0; i < m.length(); i++)
v.push_back(m[i]);
//注意下标vector的下标是从0开始的
for (ll i = m.length()-1; i >= 1; i--)
{
ll r = n % f[i];
ll s = n / f[i];
n = r;
//sort(v.begin(), v.end());
result.push_back(v[s]);
v.erase(v.begin()+s);
}
//最后一个
result.push_back(v[0]);
for (ll i = 0; i < m.length(); i++)
{
cout << result[i];
}
cout << endl;

}

int main()
{
string m;
ll n;//第 n 个
cin >> m;
cin >> n;
init(m);
Work(m, n);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息