您的位置:首页 > 其它

2019hdu暑假多校训练赛第五场1005 permutation 1 hdu 6628(全排列)

2019-08-05 21:23 316 查看

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6628

题意:给定n和k,要求用1到n求出一个序列使得这个序列后一项减前一项形成的n-1长度的序列的字典序最小。

数据范围:1≤T≤40,2≤N≤20, 1≤K≤min(1e4,N!)

 

思路:首先字典序最小的序列一定是n,1,2,3.........n-2,n-1这样的。再考虑8的阶乘是40320,9的阶乘是362880,所以9以下的直接预处理全排列找出所有的可行解,排序,对于每次访问第k大的输出即可,对于9以上的,从10开始那么第一项和第二项就是固定的a[1]=n,a[2]=1,那么剩下的n-2项是大于等于8的,由于数据小于1e4所以全排列也不会影响到第二项的1,所以直接固定前两项,对于后面的n-2项全排列k次即可

 

[code]#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
int n,m,t;
struct p{
int num[11];
char str[11];
}a[11]
;
bool cmp(p aa, p bb){
return strcmp(aa.str,bb.str)<0;
}

int main(){
int b[15]={0,1,2};
for(int k=2;k<=9;k++){

int cnt=1;
do{
for(int i=1;i<=k;i++){
a[k][cnt].num[i]=b[i];
if(i!=1)a[k][cnt].str[i-2]=b[i]-b[i-1]+'A';
}
a[k][cnt].str[k-1]='\0';
cnt++;
}while(next_permutation(b+1,b+k+1));

sort(a[k]+1,a[k]+cnt,cmp);
b[k+1]=k+1;
}
scanf("%d",&t);
while(t--){
int k;
scanf("%d%d",&n,&k);
if(n>9){
int c[30];
c[1]=n;
for(int i=2;i<=n;i++)c[i]=i-1;
for(int i=1;i<k;i++){
next_permutation(c+1,c+n+1);
}
for(int i=1;i<=n;i++){
i==1||printf(" ");
printf("%d",c[i]);
}
printf("\n");
continue;
}
for(int i=1;i<=n;i++){
i==1||printf(" ");
printf("%d",a
[k].num[i]);
}
printf("\n");
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: