编号(CQOI2012,BZOJ2665)
编号(CQOI2012)
题目大意
你需要给一批商品编号,其中每个编号都是一个7位16进制数(由0~9, a-f组成)。为了防止在人工处理时不小心把编号弄错,要求任意两个编号至少有三个位置对应的数字不相同。第一个编号为0000000,第二个编号为不违反上述规定的前提下最小的编号,…,每次分配一个新编号时,总是选择不和前面编号冲突的最小编号(注意编号都是16进制数,可以比较大小)。按此规律,前面若干编号分别是:0000000, 0000111, 0000222, …, 0000fff, 0001012, 0001103,0001230,0001321,0001456,…
输入k,你的任务是求出第k小的编号。
思路
比较神仙的\(DP\)题。
任意两个数都至少三个位置不同,说明只要存在两个数存在五个位完全相等时,就不合法了。
那么我们直接暴力标记这五个位置,记\(DP[w][a][b][c][d][e]\),\(w\)表示当前的5个数字存在于7个位中的哪5个。\(a,b,c,d,e\)表示五个数的值。那么一共存在状态\(\tbinom{5}{7}\) 21个,所以数组总共开\(21*16^5\).
我们暴力\(16^7\)次枚举每位的数字,如果前面21种状态都为\(false\),便可计入,并将这些状态都标记为\(true\)。
code
#include<bits/stdc++.h>
#define FOR(i,l,r) for(register int i=(l),i##R=(r);i<=i##R;i++)
#define DOR(i,r,l) for(register int i=(r),i##L=(l);i>=i##L;i--)
#define loop(i,n) for(register int i=0,i##R=(n);i<i##R;i++)
#define mms(a,x) memset(a,x,sizeof a)
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
template<typename A,typename B>inline void chkmax(A &x,const B y){if(x<y)x=y;}
template<typename A,typename B>inline void chkmin(A &x,const B y){if(x>y)x=y;}
const int N=(1<<28),M=2e5+5;
int K;
int dp[25][16][16][16][16][16];
void Print(int a[]){
loop(i,7)
printf("%c",a[i]>=10?a[i]-10+'a':a[i]+'0');
}
void solve(){
loop(a,16)loop(b,16)loop(c,16)loop(d,16)loop(e,16)loop(f,16)loop(g,16){
if(
!dp[1][a][b][c][d][e]&&
!dp[2][a][b][c][d][f]&&
!dp[3][a][b][c][d][g]&&
!dp[4][a][b][c][e][f]&&
!dp[5][a][b][c][e][g]&&
!dp[6][a][b][c][f][g]&&
!dp[7][a][b][d][e][f]&&
!dp[8][a][b][d][e][g]&&
!dp[9][a][b][d][f][g]&&
!dp[10][a][b][e][f][g]&&
!dp[11][a][c][d][e][f]&&
!dp[12][a][c][d][e][g]&&
!dp[13][a][c][d][f][g]&&
!dp[14][a][c][e][f][g]&&
!dp[15][a][d][e][f][g]&&
!dp[16][b][c][d][e][f]&&
!dp[17][b][c][d][e][g]&&
!dp[18][b][c][d][f][g]&&
!dp[19][b][c][e][f][g]&&
!dp[20][b][d][e][f][g]&&
!dp[21][c][d][e][f][g]
)
{
K--;
if(!K){
int A[7]={a,b,c,d,e,f,g};
Print(A);
return;
}
dp[1][a][b][c][d][e]=1;
dp[2][a][b][c][d][f]=1;
dp[3][a][b][c][d][g]=1;
dp[4][a][b][c][e][f]=1;
dp[5][a][b][c][e][g]=1;
dp[6][a][b][c][f][g]=1;
dp[7][a][b][d][e][f]=1;
dp[8][a][b][d][e][g]=1;
dp[9][a][b][d][f][g]=1;
dp[10][a][b][e][f][g]=1;
dp[11][a][c][d][e][f]=1;
dp[12][a][c][d][e][g]=1;
dp[13][a][c][d][f][g]=1;
dp[14][a][c][e][f][g]=1;
dp[15][a][d][e][f][g]=1;
dp[16][b][c][d][e][f]=1;
dp[17][b][c][d][e][g]=1;
dp[18][b][c][d][f][g]=1;
dp[19][b][c][e][f][g]=1;
dp[20][b][d][e][f][g]=1;
dp[21][c][d][e][f][g]=1;
}
}
}
int main(){
scanf("%d",&K);
solve();
return 0;
}