首先必须要说一下,这是我看了别人的思路以后去自己想的此处是 思路来源:杭电2062__WM_的博客-CSDN博客
什么是字典排序呢:
我举个例子你去品位:
1
12
123
13
132
2
21
213
23
231
3
31
312
32
321
说一下我的思路:
首先目的是找An的第m项,程序必须对输入的任意m有效,所以一定有规律可循。
对于An为{1, 2, 3, 4, .. , n};每个An分组根据首数字按顺序(1,2,3…)分组。给定一个m,可以根据每组的项数去锁定m在第几组。每组的项数其实就是一个周期(1过完了就是2,2过完了就是3)。周期又等于子集总数/n。总数的规律:
A1 – 1 A2-4 A3-15,在An,有n个数字,确定一个数字后,剩下的就是An-1和 多出来的数字个数 * n,这里我打字不知道怎么讲清楚,我还是在纸上呈现吧:
这也是后面得到答案的关键思想
确定好了总数,乘上一个n就是周期的n项了:n*T_n = n * ((n-1)*T_(n-1) + 1),两边消一消,就变成了:T_n = T_(n-1) * (n - 1) + 1;
最后每次找变化中的n的第几周期(因为是按照顺序来的),所以第几周期就打印谁,不断减少n,并且消去打印的元素。向n = 1 递归。
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <ctype.h>
#include <iomanip>
#include <vector>
#include <array>
#include <limits.h>
#include <algorithm> //算法
#define N 100
using namespace std;
int main()
{
int n, m;
while((scanf("%d %d",&n,&m)) != EOF)
{
long long int T[21];
T[1] = 1;
T[2] = 2;
for(int i = 3 ; i < 21 ; i++)
{
T[i] = T[i-1] * (i - 1) + 1;
}
int nums[21];
for(int i = 1 ; i < 21 ; i++)
{
nums[i] = i;
}
// 找An的第m项:
long long int t = 0;
while(m != 0)
{
//查看在当前n下的第几周期情况:
t = (m-1) / T[n] + 1;
cout << nums[t];
for(int i = t ; i < 21 ; i++)
{
nums[i] = nums[i+1];
}
// 打印一个数字后:确定它在新分组后的低第几位数
m = m - (t - 1) * T[n] - 1; // -1是减去拿走的nums[t]
n --; // 举例:原本是{1,2,3} 拿走一个后 变成了 {1,2} 就是在新生成的{1,2}中找也就是n = 2这种情况去排列后面的元素
if(n == 0)
{
break;
}
if(m == 0)
{
break;
}
else
{
cout << ' ';
}
}
cout << endl;
}
return 0;
}