题干:
给你两个6行5列的字母表,一个整数k,两个表中第i列相同的字母可能是密码第i的字母,将所有可能性升序排列,求排完序后第k中可能性的密码是什么,如果不存在输出no。
思路:
模拟…将存储的数组按列遍历,然后存到vector中,sort排序,unique去重,然后根据后缀积,求在vector中的位置。
细节见代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
char a[10][10],b[10][10];
vector<char>x[10];
int ans[10],h[10];
int main()
{
int t,n;
//FILE *fp;
//fp=fopen("DATA.txt", "w");
scanf("%d",&t);
while(t--)
{
int flag=0;
for(int i=0;i<5;i++)
x[i].clear();
memset(ans,0,sizeof(ans));
memset(h,0,sizeof(h));
scanf("%d",&n);
for(int i=0;i<6;i++)
scanf("%s",a[i]);
for(int i=0;i<6;i++)
scanf("%s",b[i]);
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
for(int k=0;k<6;k++){
if(a[j][i]==b[k][i]) //按列遍历
x[i].push_back(a[j][i]);
}
}
}
for(int i=0;i<5;i++){
sort(x[i].begin(),x[i].end()); //排序
unique(x[i].begin(),x[i].end()); //去重
if(x[i].empty()) //判断是否为空
{
flag=1;
break;
}
while(ans[i]<x[i].size()-1&&x[i][ans[i]+1]>x[i][ans[i]]) //因为unique去重是将重复的变成不重复的
ans[i]++;
ans[i]++; //因为至少一个
//printf("%d\n",ans[i]);
}
if(flag) //判断vector数组是否为空,注意这一点
{
printf("NO\n");
continue;
}
h[5]=1;
for(int i=4;i>=0;i--){
h[i]=1;
h[i]=ans[i]*h[i+1]; //求后缀积
}
if(n>h[0]) //判断是否超限
printf("NO\n");
else{
n--;
for(int i=0;i<5;i++){
printf("%c",x[i][n/h[i+1]]); //求位置
n%=h[i+1];
}
printf("\n");
}
}
return 0;
}