OI:校内模拟赛 T2:Tavan —— 字符操作,k进制转换

1 篇文章 0 订阅
1 篇文章 0 订阅

模拟赛的题,内容主要考察的是字符串操作,字典序,和类似于k进制的转换,有兴趣的同学可以来看看。
题目真的是又臭又长。

#3369. Tavan
内存限制:32 MiB
时间限制:1000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
上传者: cqbzgm
题目描述
小 Zeljko 一直在阁楼里读他奶奶的旧信,并且发现了一个长度为 N 的单词。 不幸的是,由于溢出的墨水,他不知道单词的内容。他把看不清的 M 个字母每 个字母都用一个字符’#‘替换后,在一张纸上重写了这个词。他把那张纸递给 了他的奶奶,对于每个看不清的字母,奶奶给了他 K 个不同的可能。在那之后, Zeljko 在笔记本中写下了所有可能的单词,并决定仔细查看他们的属性,以确 定原始单词是什么。在看到笔记本上写下的单词后,他的奶奶意识到他们正在 寻找的是按字典序排列的第 X 个单词。Zeljko 在他们学校学习字母表的那天生 病了,所以他要求你帮助他确定原来的单词。 输入 第一行输入包含整数 N,M,K 和 X(1≤N≤500,1≤M≤N,1≤K≤26,1≤X≤ 1e9)。分别表示单词的长度,看不清的字母的数量,奶奶给出的字母的数量和 原单词是字典序的第几个。 第二行输入包含一个长度为 N 的字符串,由小写英文字母和字符’#‘组成。 表示 Zeljko 找到的单词,其中字符’#'表示看不清的字母。 接下来 M 行中的每一行包含一个长度为 K 的字符串,由 K 个不同的小写英文 字母组成。第 2+i 行的 K 个字母表示第 i 个看不清的 保证 X 总是小于等于能构造出的单词的总数。

输入格式
第一行输入包含整数 N,M,K 和 X(1≤N≤500,1≤M≤N,1≤K≤26,1≤X≤ 1e9)。分别表示单词的长度,看不清的字母的数量,奶奶给出的字母的数量和 原单词是字典序的第几个。 第二行输入包含一个长度为 N 的字符串,由小写英文字母和字符’#‘组成。 表示 Zeljko 找到的单词,其中字符’#'表示看不清的字母。 接下来 M 行中的每一行包含一个长度为 K 的字符串,由 K 个不同的小写英文 字母组成。第 2+i 行的 K 个字母表示第 i 个看不清的字母的 K 种可能。 保证 X 总是小于等于能构造出的单词的总数。

输出格式
输出一个字符串。表示原本的单词。

样例
样例输入
9 2 3 7
po#olje#i
sol
znu
样例输出
posoljeni
数据范围与提示
对于 30%的数据,M=1 并且 K=3。 对于另外 30%的数据,M=1。

可能题目描述的不清楚,我来大致介绍一下题意。
给出一个字符串,"#“的位置可以由给出的几个字母来替换,比如第一个井号就可以是"s”,“o"和"l”,第二个井号就可以是"z",“n"和"u”。
这样这个字符串就有 3 2 3^2 32(题目中 M K M^K MK)种可能的形态,将这 M K M^K MK种情况排列,答案便是其中的第X个。

所以我们可以将字符串简化成K个井号,因为其它的字符都是固定的,对字典序的排列没有影响。

我们只需要将每个井号可能的字母从小到大排序,那么便可以得到:
l , o , s l,o,s l,o,s n , u , z n,u,z n,u,z,因为每个井号有k种情况,那么只需要将 X − 1 X-1 X1(因为我们要给第一位留个位置)转换为 K K K进制。样例中对应的便是 20 20 20,对应字母的情况就是 31 31 31,也就是 l , o , s l,o,s l,o,s的第三个字母和 n , u , z n,u,z n,u,z的第一个字母。
k进制的转换这里不详讲,详细见代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

#define N 5005
#define LL long long

string a;
LL n,m,k,x,T=1,ans[N];
char A[N][N];

int main() {
	cin>>n>>m>>k>>x;
	cin>>a;
	for(LL i=1;i<=m;i++) {
		LL P[N];
		for(LL j=0;j<k;j++) cin>>A[i][j];//排序
		for(LL j=0;j<k;j++) P[j]=A[i][j];
		sort(P,P+k);
		for(LL j=0;j<k;j++) A[i][j]=(char)P[j];
	}
	LL cnt=0,x1=x-1;
	for(LL i=m;i>=1;i--) {//k进制转换
        ans[i]=x1%k;
        x1/=k; 
	}
	for(LL i=0;i<a.length();i++) {//输出答案
		if(a[i]=='#') {
            cnt++;
            cout<<A[cnt][ans[cnt]];
		}
		else cout<<a[i];
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值