题意:
给出两个6行5列的字母矩阵,一个密码满足:密码的第i个字母在两个字母矩阵的第i列均出现。
然后找出字典序为k的密码,如果不存在输出NO
分析:
我们先统计分别在每一列均在两个矩阵出现的字母,然后从小到大排好序。
对于第一个样例来说,我们得到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开始的。
1 //#define DEBUG 2 #include <cstdio> 3 #include <cstring> 4 5 char G[2][6][5], ans[6], select[6][5]; 6 int vis[2][26], hehe[6], cnt[5]; 7 8 int main() 9 { 10 //freopen("in.txt", "r", stdin); 11 12 int T; 13 scanf("%d", &T); 14 hehe[5] = 1; 15 while(T--) 16 { 17 memset(cnt, 0, sizeof(cnt)); 18 int k; 19 scanf("%d", &k); 20 k--; //字典序标号从0开始 21 for(int i = 0; i < 2; ++i) 22 for(int j = 0; j < 6; ++j) 23 scanf("%s", G[i][j]); 24 25 for(int i = 0; i < 5; ++i) 26 { 27 memset(vis, 0, sizeof(vis)); 28 for(int j = 0; j < 2; ++j) 29 for(int k = 0; k < 6; ++k) 30 vis[j][G[j][k][i]-'A'] = 1; 31 for(int j = 0; j < 26; ++j) 32 if(vis[0][j] && vis[1][j]) 33 select[i][cnt[i]++] = 'A' + j; 34 } 35 36 #ifdef DEBUG 37 for(int i = 0; i < 5; ++i) 38 { 39 for(int j = 0; j < select[i].size(); ++j) 40 printf("%c", select[i][j]); 41 puts(""); 42 } 43 #endif // DEBUG 44 45 for(int i = 4; i >= 0; --i) 46 hehe[i] = cnt[i] * hehe[i+1]; 47 if(k >= hehe[0]) 48 { 49 puts("NO"); 50 continue; 51 } 52 for(int i = 0; i < 5; ++i) 53 { 54 int m = k / hehe[i+1]; 55 ans[i] = select[i][m]; 56 k = k % hehe[i+1]; 57 } 58 ans[5] = '