题解 UVA1262 【Password】

题目链接:Link

Solution

首先,先按列处理出所有合法的字母,按字典序排列。

注意!有可能会有相同的字母!

接下来,从左到右计算应该选那个字母(无解的情况预处理一下就行了)

#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int T,k;
bool found[7][128];
char x;
vector<char> can[7];
int last[7];
int main()
{
#ifdef local
	freopen("pro.in","r",stdin);
#endif
	scanf("%d",&T);
	while(T-->0)
	{
		memset(found,0,sizeof(found));
		for(int i=1;i<=5;i++) can[i].clear();
		cin>>k;
		for(int i=1;i<=6;i++)
			for(int j=1;j<=5;j++)
				found[j][cin>>x,x]=1;
		for(int i=1;i<=6;i++)
			for(int j=1;j<=5;j++)
				if(found[j][cin>>x,x])
				{
					can[j].push_back(x);
					found[j][x]=0;
				}
		for(int i=1;i<=5;i++) sort(can[i].begin(),can[i].end());
		last[5]=1;
		for(int i=4;i>=0;i--) last[i]=last[i+1]*can[i+1].size();
		if(k>last[0]) cout<<"NO"<<endl;
		else
		{
			for(int i=1;i<=5;i++)
			{
			    int j=ceil((double)k/last[i])-1;
                /*
                计算出该用哪个字母。
                ∵ 如果 last[i]*(j+1)>=k 则用当前字符
                ∴ 向上取整再减1就是下标。
                */
			    cout<<can[i][j];
			    k-=last[i]*j;
			}
			cout<<endl;
		}
	}
	return 0;
}
posted @ 2019-08-19 21:52  happyZYM  阅读(104)  评论(0编辑  收藏  举报