编号(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;
}
posted @ 2019-09-01 18:47  Hëinz  阅读(205)  评论(0编辑  收藏  举报