题意:给出两个6行5列的字母矩阵,一个密码满足:密码的第i个字母在两个字母矩阵的第i列均出现。然后找出字典序为k的密码,如果不存在输出NO
分析:紫书题解,
解法1:我们先统计分别在每一列均在两个矩阵出现的字母,然后从小到大排好序。
对于第一个样例来说,我们得到ACDW、BOP、GMOX、AP、GSU
则一共有4×3×4×2×3=288种密码,我们先计算这个数列的后缀积:288、72、24、6、3、1
要确定第一个字母,如果1≤k≤72,则是A;如果73≤k≤144,则是C,以此类推。
确定第二个字母是类似的,用k%72+1与24去比较。
代码实现中,字典序是从0开始的。
解法二:
因为密码最多有65 = 7776种,所以可以按字典序从小到大枚举。
思维难度小,写起来更快更对。
代码如下:
//
//Created by BLUEBUFF 2016/1/11
//Copyright (c) 2016 BLUEBUFF.All Rights Reserved
//
#pragma comment(linker,"/STACK:102400000,102400000")
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/hash_policy.hpp>
//#include <bits/stdc++.h>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <time.h>
#include <cstdlib>
#include <cstring>
#include <complex>
#include <sstream> //isstringstream
#include <iostream>
#include <algorithm>
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, LL> pp;
#define REP1(i, a, b) for(int i = a; i < b; i++)
#define REP2(i, a, b) for(int i = a; i <= b; i++)
#define REP3(i, a, b) for(int i = a; i >= b; i--)
#define CLR(a, b) memset(a, b, sizeof(a))
#define MP(x, y) make_pair(x,y)
template <class T1, class T2>inline void getmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void getmin(T1 &a, T2 b) { if (b<a)a = b; }
const int maxn = 50010;
const int maxm = 1e5+5;
const int maxs = 10;
const int maxp = 1e3 + 10;
const int INF = 1e9;
const int UNF = -1e9;
const int mod = 1e9 + 7;
const int rev = (mod + 1) >> 1; // FWT
const double PI = acos(-1);
//head
int k, cnt;
char G[2][6][5], ans[6];
bool dfs(int col){
if(col == 5){
if(++cnt == k){
ans[col] = '\0';
printf("%s\n", ans);
return true;
}
return false;
}
bool vis[2][26];
memset(vis, false, sizeof(vis));
for(int i = 0; i < 2; i++){
for(int j = 0; j < 6; j++){
vis[i][G[i][j][col] - 'A'] = 1;
}
}
for(int i = 0; i < 26; i++){
if(vis[0][i] && vis[1][i]){
ans[col] = i + 'A';
if(dfs(col + 1)) return true;
}
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while(T--){
scanf("%d", &k);
for(int i = 0; i < 2; i++){
for(int j = 0; j < 6; j++){
scanf("%s", G[i][j]);
}
}
cnt = 0;
if(!dfs(0)) puts("NO");
}
return 0;
}