康拓展开参考网站:https://www.cnblogs.com/Howe-Young/p/4348777.html
康拓展开在我个人开来就是找出所有没出现的数中比当前位置要小的数的个数然后将个数 * 阶乘
举个例子
1 3 2 4 比1小的有0 个 0 * 3!比3小的有两个但是1已经出现过了所有只有一个 1 * 2!再看2比2小的有一个但是出现过了所以
0 * 1! 最后在加上1就是这个排列出现的位置
练习康拓展开可以刷这道题http://nyoj.top/problem/139
nyoj 139 ac代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll maxn = 1e5 + 5;
const ll mod = 1000000007;
//b的作用是算出阶乘;
ll b[maxn];
void init(ll *b)
{
b[0] = 1;
for(int i = 1; i <= 12; i ++)
{
b[i] = i * b[i - 1];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll t;
string s;
cin >> t;
init(b);
while(t--)
{
// sum是统计比当前小的数的个数
ll flag[100] = {0},sum = 0,ans = 0;
cin >> s;
ll m = s.length();
for(int i = 0; i < m; i ++)
{
sum = 0;
ll be = s[i] - 'a';
flag[be] = 1;
for(int j = 0; j <= 11; j ++)
{
if(flag[j] == 0)
{
if(be > j)
{
sum ++;
}
}
}
ans += b[12 - i - 1] * sum;
}
cout << ans + 1 << endl;
}
return 0;
}
康拓逆展开就是 将这个数除以阶乘 找出有几个比当前位置小的数然后枚举找出
练习康拓逆展开可以刷这道题http://nyoj.top/problem/143
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll maxn = 1e5 + 5;
const ll mod = 1000000007;
//b的作用是算出阶乘;
ll b[maxn];
void init(ll *b)
{
b[0] = 1;
for(int i = 1; i <= 12; i ++)
{
b[i] = i * b[i - 1];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll t;
cin >> t;
init(b);
while(t--)
{
ll flag[100] = {0};
ll n;
cin >> n;
n -= 1;
for(int i = 0; i < 12; i ++)
{
//be是比当前位置小的有几个数
ll be = n / b[12 - i - 1];
n %= b[12 - i - 1];
ll sum = 0;
for(int j = 0; j < 12; j ++)
{
if(sum == be && flag[j] == 0)
{
flag[j] = 1;
cout << char('a' + j);
break;
}
if(flag[j] == 0)
{
sum++;
}
}
}
cout << endl;
}
return 0;
}