算法基础精选题3.13 模拟

第一题

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题号:NC16644
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或“4-8”的子串,我们就把它当作一种简写,输出时,用连续递增的字母或数字串替代其中的减号,即,将上面两个子串分别输出为“defgh”和“45678”。在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活。具体约定如下:
(1)遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号“-”,减号两侧同为小写字母或同为数字,且按照ASCII码的顺序,减号右边的字符严格大于左边的字符。
(2)参数 p1p_1p1​:展开方式。p1=1p_1=1p1​=1 时,对于字母子串,填充小写字母;p1=2p_1=2p1​=2 时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。p1=3p_1=3p1​=3时,不论是字母子串还是数字子串,都用与要填充的字母个数相同的星号“*”来填充。
(3)参数 p2p_2p2​:填充字符的重复个数。p2=kp_2=kp2​=k 表示同一个字符要连续填充 kkk 个。例如,当 p2=3p_2=3p2​=3 时,子串“d-h”应扩展为“deeefffgggh”。减号两侧的字符不变。
(4)参数 p3p_3p3​:是否改为逆序:p3=1p_3=1p3​=1 表示维持原有顺序,p3=2p_3=2p3​=2 表示采用逆序输出,注意这时仍然不包括减号两端的字符。例如当 p1=1、p2=2、p3=2p_1=1、p_2=2、p_3=2p1​=1、p2​=2、p3​=2 时,子串“d-h”应扩展为“dggffeeh”。
(5)如果减号右边的字符恰好是左边字符的后继,只删除中间的减号,例如:“d-e”应输出为“de”,“3-4”应输出为“34”。如果减号右边的字符按照ASCII码的顺序小于或等于左边字符,输出时,要保留中间的减号,例如:“d-d”应输出为“d-d”,“3-1”应输出为“3-1”。

 

输入描述:

第 1 行为用空格隔开的 3 个正整数,依次表示参数 p1,p2,p3p_1,p_2,p_3p1​,p2​,p3​。
第 2 行为一行字符串,仅由数字、小写字母和减号“-”组成。行首和行末均无空格。

输出描述:

输出一行,为展开后的字符串。

示例1

输入

复制1 2 1 abcs-w1234-9s-4zz

1 2 1
abcs-w1234-9s-4zz

输出

复制abcsttuuvvw1234556677889s-4zz

abcsttuuvvw1234556677889s-4zz

示例2

输入

复制2 3 2 a-d-d

2 3 2
a-d-d

输出

复制aCCCBBBd-d

aCCCBBBd-d

示例3

输入

复制3 4 2 di-jkstra2-6

3 4 2
di-jkstra2-6

输出

复制dijkstra2************6

dijkstra2************6

备注:

40%40\%40% 的数据满足:字符串长度不超过5
100%100\%100% 的数据满足:1≤p1≤3,1≤p2≤8,1≤p3≤21 ≤ p_1 ≤ 3, 1 ≤ p_2 ≤ 8, 1 ≤ p_3 ≤ 21≤p1​≤3,1≤p2​≤8,1≤p3​≤2。字符串长度不超过100

 

对于本题其实

很久其实在我刚刚写博客的时候就已经写过,今天重新温故一下这道题

 

首先对于题干很长,我们先多读两遍,接着提取关键信息比方说题干要我们干什么,最终要输出什么,如何实现。那么接下来我们,一步步来拆解。首先对于输出,即要展开的字符串,按照题干,只有出现-时展开  因此直接遍历,并且数组不能越界,那么必须要保证当前遍历字符左边要>=0右边<n  这里直接定义一个新的字符串,如果出现-,则将展开后的内容加入,如果没出现-,则加入当前字符,接着就是实现展开的具体内容。

先有一个大方向,如果出现-后,但是右边刚好是左边的后继,则直接返回“”,如果不满足当前字符两边都是数字字符或者都是字母字符,并且右边严格大于左边,那么返回
“-”  即不展开。接着定义ans字符串作为展开后的字符串加入的字符串,从b+1开始到e-1结束,篇

表示重复的次数。接着由p1确定是否要变成大写,最后由p3确定是否变成*,这么一套逻辑下来,思路清晰了,代码就好实现了。

 

 

#include<bits/stdc++.h>
using namespace std;
int p1, p2, p3;
string s, ans;
string fun(char b, char e, int p1, int p2, int p3)
{
	if (e - b == 1)
		return "";//不展开
	//何时输出“-”;
	if (!((isalpha(b) && isalpha(e) && b < e) ||
		(isdigit(b) && isdigit(e) && b < e)))
	{
		return "-";
	}
	string ans = "";
	//接着将要展开的放到ans
	for (char t = b + 1; t < e; t++)
	{
		for (int i = 0; i < p2; i++)
		{
			ans += t;
		}
	}
	//判断是否大小写
	if (p1 == 2 && isalpha(b) && isalpha(e))
	{
		for (int i = 0; i < ans.length(); i++)
		{
			ans[i] = ans[i] - 'a' + 'A';
		}
	}
	if(p1 == 3)
	{
		for (int i = 0; i < ans.length(); i++)
		{
			ans[i] = '*';
		}
	}
	if (p3 == 2)
	{
		reverse(ans.begin(), ans.end());
	}
	return ans;
}
int main() {
	cin >> p1 >> p2 >> p3;
	cin >> s;
	for (int i = 0; i < s.length(); i++)
	{
		if (s[i] == '-' && i - 1 >= 0 && i+1 < s.length())
			ans += fun(s[i - 1], s[i + 1], p1, p2, p3);
		else
			ans += s[i];
	}
	cout << ans;

	return 0;
}

 

第二题:

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

一元n次多项式可用如下的表达式表示:

f (x) = anxn+ an-1xn-1 + ... + a1x + a0,a0≠0

其中,aixi 称为i 次项,ai 称为i次项的系数。给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求输出该多项式:

1. 多项式中自变量为x,从左到右按照次数递减顺序给出多项式。

2. 多项式中只包含系数不为0的项。

3. 如果多项式n次项系数为正,则多项式开头不出现“+”号,如果多项式 n 次项系数为负,则多项式以“-”号开头。

4. 对于不是最高次的项,以“+”号或者“-”号连接此项与前一项,分别表示此项系数为正或者系数为负。紧跟一个正整数,表示此项系数的绝对值(如果一个高于0 次的项,其系数的绝对值为1,则无需输出1)。如果x的指数大于1,则接下来紧跟的指数部分的形式为“x^b”,其中b为x的指数;如果x的指数为1,则接下来紧跟的指数部分形式为“x”;如果x的指数为0,则仅需输出系数即可。

5. 多项式中,多项式的开头、结尾不含多余的空格。

输入描述:

第一行1个整数,n,表示一元多项式的次数。
第二行有n+1 个整数,其中第i 个整数表示第n-i+1 次项的系数,每两个整数之间用空格隔开。

输出描述:

共1行,按题目所述格式输出多项式。

示例1

输入

复制5 100 -1 1 -3 0 10

5
100 -1 1 -3 0 10

输出

复制100x^5-x^4+x^3-3x^2+10

100x^5-x^4+x^3-3x^2+10

示例2

输入

复制3 -50 0 0 1

3
-50 0 0 1

输出

复制-50x^3+1

-50x^3+1

备注:

1≤n≤100,多项式各次项系数的绝对值均不超过100。

对于本题,明确一个大的方向,即步步实现先确定系数,再确定符号再确定系数,接着确定x然后确定次数。

我们从后往前遍历,如果当前最高次的系数为负数,那么输出-,否则不用管,因为是首位,如果不是最高次,那么只要系数大于0,那么就输出+小于0就输出-,接着判断系数,如果说系数为-1或者系数为1,并且不是常数项,那么就不输出,否则输出其绝对值,如果是不是常数项或者是一次项,那么输出x……,如果是一次项就直接输出x

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N];
int main()
{
	int n;
	cin >> n;
	for (int i = n; i >= 0; i--)
		cin >> a[i];
	for (int i = n; i >= 0; i--)
	{
		if (a[i] == 0) continue;//处理特殊情况,系数为0的时候不用输出
			if (i == n)
			{
				if (a[i]<0)
					cout << "-";
			}
			else
			{
				//不是最高项数
				if (a[i] > 0)
				{
						cout << "+";
				}
				else
					cout << "-";
			}
		//接着判断系数
		if ((a[i] == 1 || a[i] == -1) && i != 0)
			;
		else
			cout << abs(a[i]);
		if (i != 1 && i != 0) cout << "x^" << i;
		else if (i == 1) cout << "x";
	}


	return 0;
}

第三题:

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。

这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。

假设内存中有 MMM 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过 M−1M−1M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入MMM 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。

假设一篇英语文章的长度为 NNN 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

 

 

输入描述:

输入共 2 行。每行中两个数之间用一个空格隔开。
第一行为两个正整数 MMM 和 NNN,代表内存容量和文章的长度。
第二行为 NNN 个非负整数,按照文章的顺序,每个数(大小不超过 1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。

输出描述:

共 1 行,包含一个整数,为软件需要查词典的次数。

示例1

输入

复制3 7 1 2 1 5 4 4 1

3 7
1 2 1 5 4 4 1

输出

复制5

5

说明

整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况:
空:内存初始状态为空。
1. 1:查找单词1 并调入内存。
2. 1 2:查找单词2 并调入内存。
3. 1 2:在内存中找到单词1。
4. 1 2 5:查找单词5 并调入内存。
5. 2 5 4:查找单词4 并调入内存替代单词1。
6. 2 5 4:在内存中找到单词4。
7. 5 4 1:查找单词1 并调入内存替代单词2。
共计查了5次词典。

备注:

对于 10%10\%10% 的数据有 M=1,N≤5M=1,N ≤5M=1,N≤5。
对于100%100\%100% 的数据有 0<M≤1000<M ≤ 1000<M≤100,0<N≤10000<N ≤ 10000<N≤1000

对于本题, vis[N]:标记是否存在该内存中

temp[N]表示一个数组,用来记录加载到内存中的数字的顺序

tempos  用来记录temp数组当前的位置

对于主循环,先输入num  判断是否在字典中,如果在,continue,不在

就把字典数cnt++  接着判断空间是否满,如果满了 ,那么就要把内存中第一个元素踢掉,注意是内存中第一个,用tempos-m表示内存中的第一个,temp[temPos - m]表示当前的数字,vis[temp[temPos - m]]表示是否存在,接着标记该数字存在,然后存入temp中。

如果空间没满,那么标记num 已经放到temp中,接着放入temp  然后count++表示内存多了一个元素

 

 

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int vis[N], temp[N], temPos, m, n;
int main()
{
	cin >> m >> n;
	int count = 0;//内存空间的数字个数
	int cnt = 0;//查找字典的次数
	int num;//记录输入进来的文章
	int i;
	for (int i = 1; i <= n; i++)
	{
		cin >> num;
		//如果数字在内存空间中,则进入下一次循环
		if (vis[num] == 1)
			continue;
		cnt++;//没在的话就直接查字典数++
		//接着判断空间是否满,如果满了就要置空
		if (count >= m)
		{
			vis[temp[temPos - m]] = 0;// 剔除  对头元素   temp[tempos-m]  //表示这个数被弄掉
			vis[num] = 1;//   标记还在不在
			temp[temPos++] = num;//  字典里数
		}
		else
		{
			vis[num] = 1;
			temp[temPos++] = num;
			count++;
		}
	}
	cout << cnt << endl;



	return 0;
}

 

 

 

 

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值