题意:有两个图,每一列都存在的字母选作密码,就第k大的密码
思路:
找出各个位置上的密码,
假设:
第1个字母只能是{A,C,D,W},
第2个字母只能是{B,O,P},
第3个字母只能是{G,M,O,X},
第4个字母只能是{A,P},
第5个字母只能是{G,S,U}。
不管第1个字母是多少,后4个字母都有3*4*2*3=72种可能,因此当k≤72时,第1个字母
是A,当72<k≤144时第1个字母是C,如此等等。再用同样的方法确定第2,3,4,5个字母即
可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
char tmap[2][20][10];
vector<char>mp[10];
int vis[2][20][30];//第i个图,第j列的x字母
int num[10];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int k;
scanf("%d",&k);
memset(vis,0,sizeof(vis));
for(int j = 0; j < 2; j++)
for(int i = 0; i < 6; i ++)
scanf("%s",tmap[j][i]);
for(int i=0; i<5; ++i)
for(int j=0; j<6; ++j)
{
vis[0][i][tmap[0][j][i]-'A']=true;
vis[1][i][tmap[1][j][i]-'A']=true;
}
for(int i = 0;i < 5;i++)
mp[i].clear();
for(int i = 0;i < 5;i++)
{
for(int j = 0;j <= 26;j++)
{
if( vis[0][i][j] && vis[1][i][j])
mp[i].push_back(j + 'A');
}
}
num[5] = 1;
for(int i = 4; i >= 0; i--)
{
num[i] = num[i+1] * (int)mp[i].size();
}
if(k > num[0])
printf("NO\n");
else
{
k--;
for(int i = 0; i < 5; i++)
{
putchar(mp[i][k/num[i+1]]);
k %= num[i+1];
}
printf("\n");
}
}
return 0;
}