题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6628
题意:给你一个n,和一种序列,让你找出第k小的序列
思路:由于让你找的k最大不超过10000,8!就是40000多了,所以最多排列后8项就可以了,负数越小的,序列的字典序越小;
1、n>8时,先让最大的那个n放在开头,然后从排列n-1 到n-8,然后让数字做差,得到特殊的序列,用字符串存起来,最后排序找到第k小,然后输出当前的8项,剩下的按原顺序输出,
2、n<=8时,直接排列,找到第k小
注意字符串要用char 用string 会超时
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
struct hh{
char s[60];
int id;
}b[50000];
int bb[50000][21];
int a[25];
bool cmp(hh a,hh b){
return strcmp(a.s, b.s) < 0;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
int cnt=0;
if(n <= 8){
for (int i = 1; i <= n;i++) a[i]=i;
do{
b[++cnt].id=cnt;
for (int i = 1; i <= n;i++){
bb[cnt][i]=a[i];
}
int sum=0;
for (int i = 2; i <= n;i++){
int w=a[i]-a[i-1];
w+=60;
if(w>=0&&w<10){
b[cnt].s[sum]=(char)(w+'0');
sum++;
}
else if(w>=10){
int w1=w%10;
int w2=w/10;
b[cnt].s[sum++]=(char)(w2+'0');
b[cnt].s[sum++]=(char)(w1+'0');
}
}
b[cnt].s[sum] = '\0';
}while(next_permutation(a+1,a+1+n));
sort(b+1,b+cnt+1,cmp);
for (int i = 1; i < n;i++){
printf("%d ",bb[b[k].id][i]);
}
printf("%d\n",bb[b[k].id][n]);
}
else {
printf("%d",n);
n--;
for (int i = 1; i <= n-8;i++){
printf(" %d",i);
}
for (int i = 1; i <= 8;i++) a[i]=n-8+i;
do{
b[++cnt].id=cnt;
for (int i = 1; i <= 8;i++){
bb[cnt][i]=a[i];
}
int sum = 0;
int www=a[1]-n+8;
www+=60;
if(www>=0&&www<10){
b[cnt].s[sum++]=(char)(www+'0');
}
else if(www>=10){
int w1=www%10;
int w2=www/10;
b[cnt].s[sum++]=(char)(w2+'0');
b[cnt].s[sum++]=(char)(w1+'0');
}
for (int i = 2; i <= 8;i++){
int w=a[i]-a[i-1];
w+=60;
if(w>=0&&w<10){
b[cnt].s[sum++]=(char)(w+'0');
}
else if(w>=10){
int w1=w%10;
int w2=w/10;
b[cnt].s[sum++]=(char)(w2+'0');
b[cnt].s[sum++]=(char)(w1+'0');
}
}
b[cnt].s[sum] = '\0';
}while(next_permutation(a+1,a+1+8));
sort(b+1,b+cnt+1,cmp);
for (int i = 1; i <= 8;i++){
printf(" %d",bb[b[k].id][i]);
}
printf("\n");
}
}
return 0;
}