Description
你需要给一批商品编号,其中每个编号都是一个7位16进制数(由0~9, a-f组成)。为了防止在人工处理时不小心把编号弄错,要求任意两个编号至少有三个位置对应的数字不相同。第一个编号为0000000,第二个编号为不违反上述规定的前提下最小的编号,…,每次分配一个新编号时,总是选择不和前面编号冲突的最小编号(注意编号都是16进制数,可以比较大小)。按此规律,前面若干编号分别是:0000000, 0000111, 0000222, …, 0000fff, 0001012, 0001103,0001230,0001321,0001456,…
输入k,你的任务是求出第k小的编号。
Input
第一行为整数k。
Output
输出第k小的编号(字母必须输出小写)。输入保证这个编号存在。
Sample Input
20
Sample Output
0001321
HINT
编号 | 1-3 | 4-7 | 8-10 |
k | <=200 | <=10000 | <=200000 |
可以发现其实只需要保存5个位置.
因为至少有两个位置的数不同,如果这两个位置不同,那至少有三个位置不同.
从7个数中选5个数的方案有21种.
设f[x][i][j][k][l][a][b][c]表示第x种排列5个数分别是i,j,k,l,a,b,c;
暴力枚举即可。
#include<iostream>
#include<cstdio>
#include<cstring>
int n;
bool f[22][20][20][20][20][20];
using namespace std;
void out(int i,int j,int k,int l,int a,int b,int c){
if (i<10) cout<<i;else cout<<char(i-10+(int)'a');
if (j<10) cout<<j;else cout<<char(j-10+(int)'a');
if (k<10) cout<<k;else cout<<char(k-10+(int)'a');
if (l<10) cout<<l;else cout<<char(l-10+(int)'a');
if (a<10) cout<<a;else cout<<char(a-10+(int)'a');
if (b<10) cout<<b;else cout<<char(b-10+(int)'a');
if (c<10) cout<<c;else cout<<char(c-10+(int)'a');
}
int main(){
scanf("%d",&n);
for (int i=0;i<=15;i++)
for (int j=0;j<=15;j++)
for (int k=0;k<=15;k++)
for (int l=0;l<=15;l++)
for (int a=0;a<=15;a++)
for (int b=0;b<=15;b++)
for (int c=0;c<=15;c++)
if (!f[1][k][l][a][b][c]&&!f[2][j][l][a][b][c]&&
!f[3][j][k][a][b][c]&&!f[4][j][k][l][b][c]&&
!f[5][j][k][l][a][c]&&!f[6][j][k][l][a][b]&&
!f[7][i][l][a][b][c]&&!f[8][i][k][a][b][c]&&
!f[9][i][k][l][b][c]&&!f[10][i][k][l][a][c]&&
!f[11][i][k][l][a][b]&&!f[12][i][j][a][b][c]&&
!f[13][i][j][l][b][c]&&!f[14][i][j][l][a][c]&&
!f[15][i][j][l][a][b]&&!f[16][i][j][k][b][c]&&
!f[17][i][j][k][a][c]&&!f[18][i][j][k][a][b]&&
!f[19][i][j][k][l][c]&&!f[20][i][j][k][l][b]&&
!f[21][i][j][k][l][a])
{
n--;
if (!n){
out(i,j,k,l,a,b,c);
return 0;
}
f[1][k][l][a][b][c]=1;f[2][j][l][a][b][c]=1;
f[3][j][k][a][b][c]=1;f[4][j][k][l][b][c]=1;
f[5][j][k][l][a][c]=1;f[6][j][k][l][a][b]=1;
f[7][i][l][a][b][c]=1;f[8][i][k][a][b][c]=1;
f[9][i][k][l][b][c]=1;f[10][i][k][l][a][c]=1;
f[11][i][k][l][a][b]=1;f[12][i][j][a][b][c]=1;
f[13][i][j][l][b][c]=1;f[14][i][j][l][a][c]=1;
f[15][i][j][l][a][b]=1;f[16][i][j][k][b][c]=1;
f[17][i][j][k][a][c]=1;f[18][i][j][k][a][b]=1;
f[19][i][j][k][l][c]=1;f[20][i][j][k][l][b]=1;
f[21][i][j][k][l][a]=1;
}
}
本文介绍了一种生成不冲突十六进制编号的算法,确保任意两编号至少三位置不同。通过保存五个关键位置并利用21种排列方式,实现暴力枚举以找到第k小的编号。
640

被折叠的 条评论
为什么被折叠?



