康拓扩展 (根据当前全排列来计算排名)
模板代码
#include <bits/stdc++.h>
#define lli long long int
#define ll long long
#define pii pair<int, int>
#define plli pair<lli, lli>
#define vi vector<int>
#define vlli vector<lli>
#define vlf vector<double>
#define repq(i, x, n) for(int i=x; i<=n; i++)
#define perq(i, n, x) for(int i=n; i>=x; i--)
#define rep(i, x, n) for(int i=x; i<n; i++)
#define per(i, n, x) for(int i=n; i>x; i--)
using namespace std;
const int N = 10000, INF=0x3f3f3f3f, mod=1e9+7;
int a[N], n;
bool st[N];
ll fact[N] = {1}, P[N], A[N]; // fact需要在外部初始化
void init()
{
ll res=1;
for(int i=1; i<N; i++)
fact[i]=i*res, res*=i;
}
ll cantor(ll P[], int n) // P[]为全排列,n为排列的长度,复杂度是O(N*N)
{
ll rank=1;
for(int i=1; i<=n; i++)
{
for(int j=i+1; j<=n; j++)
if(P[j]<P[i]) A[i]++;
}
for(int i=1; i<=n; i++)
rank+=A[i]*fact[n-i];
return rank;
}
int main() {
init();
int n=7;
P[1]=1;P[2]=2;P[3]=3;P[4]=4;P[5]=6;P[6]=5;P[7]=7;
cout << cantor(P, n); //输出全排列的排名
return 0;
}
逆康拓扩展(根据排名求全排列是什么样子)
模板代码
#include <bits/stdc++.h>
#define lli long long int
#define ll long long
#define pii pair<int, int>
#define plli pair<lli, lli>
#define vi vector<int>
#define vlli vector<lli>
#define vlf vector<double>
#define repq(i, x, n) for(int i=x; i<=n; i++)
#define perq(i, n, x) for(int i=n; i>=x; i--)
#define rep(i, x, n) for(int i=x; i<n; i++)
#define per(i, n, x) for(int i=n; i>x; i--)
using namespace std;
const int N = 10000, INF=0x3f3f3f3f, mod=1e9+7;
int a[N], n;
bool st[N];
ll fact[N] = {1}, P[N], A[N]; // fact需要在外部初始化
void init()
{
ll res=1;
for(int i=1; i<N; i++)
fact[i]=i*res, res*=i;
}
void iota(vector<int>::iterator it, vector<int>::iterator end, int k)
{
while(it!=end)
{
*it=k;
it++; k++;
}
}
void decanter(ll x, int n) // x为排列的排名,n为排列的长度
{
x--;
vector<int> rest(n, 0);
iota(rest.begin(), rest.end(), 1); // 将rest初始化为1,2,...,n
// for(int i=0; i<n; i++) cout << rest[i] << ' ';
// cout << endl;
for (int i = 1; i <= n; ++i)
{
A[i] = x / fact[n - i];
x %= fact[n - i];
}
for (int i = 1; i <= n; ++i)
{
P[i] = rest[A[i]];
rest.erase(lower_bound(rest.begin(), rest.end(), P[i]));
}
}
int main() {
init();
int n=65;//极限值, 太大极限值会爆精度
decanter(5, n);
for(int i=1; i<=n; i++)
cout << P[i] << ' ';
return 0;
}