简介:
给出两个6行5列的字母矩阵,一个密码满足:密码的第i个字母在两个字母矩阵的第i列均出现
然后找出字典序为k的密码,如果不存在输出NO
分析:
本题是一道经典的解码问题
我们先统计每一个位置上能放哪些字符:
对于第一个样例来说,我们得到ACDW、BOP、GMOX、AP、GSU
要确定第一个字母,如果1≤k≤72,则是A;如果73≤k≤144,则是C,以此类推
当然这道题还有一个投机取巧的方法:
因为密码最多有65 = 7776种,所以可以按字典序从小到大枚举
思维难度小,写起来更快更对
tip
但是我这个zz果断选择了第一种方法
这就导致我debug的时间大大增加
之后和暴力对拍,一开始拍出来一个一组
好像是无解的判断出了问题,但是也没找出什么问题
之后又拍,这次真的是什么都拍不出来了,但是交上去就是WA
我能怎么办呢,我也很绝望啊。。。
//这里写代码片
#include<cstdio>
#include<cstring>
#include<cstring>
#include<algorithm>
using namespace std;
int mp1[10][10],mp2[10][10];
int z[10][10],k,cnt[10],ans[10];
char s[10];
void pre()
{
int i,j,l;
memset(z,0,sizeof(z));
memset(cnt,0,sizeof(cnt));
for (i=1;i<=5;i++)
{
for (j=1;j<=6;j++)
for (l=1;l<=6;l++)
if (mp1[j][i]==mp2[l][i])
{
z[i][++cnt[i]]=mp1[j][i];
break;
}
sort(z[i]+1,z[i]+1+cnt[i]);
}
}
int solve()
{
int i,j;
int mul[10];
memset(ans,0,sizeof(ans));
mul[5]=1;
for (i=4;i>=1;i--) mul[i]=mul[i+1]*cnt[i+1];
if (mul[1]*cnt[1]<k) return 0;
for (i=1;i<=5;i++)
{
j=1;
while (j*mul[i]<k) j++;
if (k<=mul[i]*j)
{
ans[i]=z[i][j];
k-=mul[i]*(j-1);
}
}
return 1;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&k);
for (int i=1;i<=6;i++)
{
scanf("%s",&s);
for (int j=0;j<5;j++)
mp1[i][j+1]=s[j]-'A';
}
for (int i=1;i<=6;i++)
{
scanf("%s",&s);
for (int j=0;j<5;j++)
mp2[i][j+1]=s[j]-'A';
}
pre();
if (solve())
for (int i=1;i<=5;i++) printf("%c",'A'+ans[i]);
else printf("NO");
printf("\n");
}
return 0;
}