洛谷题型摘选(三)


一、P2249 【深基13.例1】查找


1.题目描述

输入 n个单调不减的(就是后面的数不小于前面的数字)非负整数,然后进行 m 次询问。对于每次询问,给出一个整数q,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 -1 。

2.输入格式

第一行 2 个整数 n 和 m,表示数字个数和询问次数。

第二行 n 个整数,表示这些待查询的数字。

第三行 m 个整数,表示询问这些数字的编号,从 1 开始编号。

3.输出格式

m 个整数表示答案。

4.输入输出样例

> 输入:
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6
> 输出:
1 2 -1 

5.做题思路

这是一道比较简单的二分法应用题,在看到有序数组时就应该想到需要使用二分法,这道题的主要特点应该就是有序数组中会出现多个相同数据.

所以就需要在写二分法的时候把这个给考虑进去,就算找到的中值等于了目标值,也并不代表该中值为答案,可能中值前面的数和它时一样的,所以需要继续往前搜寻。

6.代码

#include <stdio.h>
#include <stdlib.h>
int Found(int* p, int flag, int head, int end);
#define N 1000000
#define M 100000
int a[N], b[M];
int main()
{
	int n, m;
	scanf_s("%d %d", &n, &m);		/* 输入数字个数n和询问次数m */
	for (int i = 0; i < n; i++)		/* 输入数字 */
		scanf_s("%d", &a[i]);
	for (int i = 0; i < m; i++)
	{
		scanf_s("%d", &b[i]);	/* 输入查询的数字 */
		printf("%d ", Found(a, b[i], 0, n - 1));	/* 输出二分法函数返回值即为答案 */
	}
	return 0;
}
int Found(int* p, int flag, int head, int end)	/* 定义二分法使用函数 */
{
	int mid = 0;
	while (head < end)				/* 二分法主体 */
	{
		mid = (head + end) / 2;
		if (flag <= p[mid]) end = mid;
		else head = mid + 1;
	}
	if (flag == p[head]) return head + 1;	/* 如果满足条件,则说明找到该数字 */
	else return -1;			/* 否则输出-1 */
}

二、P1914 凯撒密码


1.题目描述

密码是由原文字符串(由不超过 50 个小写字母组成)中每个字母向后移动 n (0≤n≤26)位形成的。z 的下一个字母是 a,如此循环。他现在找到了移动前的原文字符串及 n,请你求出密码。

2.输入格式

第一行:n。第二行:未移动前的一串字母

3.输出格式

一行,是此密码

4.输入输出样例

> 输入:
1
qwe
> 输出:
rxf

5.做题思路

刚看到这道题的时候直接就写了,觉得应该一次就过了,但是测试的时候出了错误答案,当时就有些纳闷,仔细看了会才发现这道题的高深之处

‘z’的值是122,计算机中1个字符占1个字节,也就是8位,其大小最大为2^7 - 1=127,如果给’z’向后移5位以上,它的值就会溢出,导致最后的结果错误,为了解决这个问题,需要先把字符的值缩小,保证在’z’+26时不会溢出,最后重置后,再把值放大。

6.代码

#include <stdio.h>
#include <stdlib.h>
int main()
{
	char ch[50];
	int n, i = 0;
	scanf_s("%d", &n);		/* 输入位移量n */
	scanf_s("%s", ch, 50);		/* 输入该字符串 */
	while (ch[i] != '\0')		/* 读取整个字符串 */
	{
		ch[i] -= 'a' - 1 - n;		/* 将字符的值先缩小,防止溢出 */
		if (ch[i] > 26) ch[i] -= 26;	/* 将超出'z'值的字母从头开始,即'z'+ 1='a' */
		ch[i] += 'a' - 1;			/* 再将字符放大为原来的值 */
		i++;		/* 继续读取下一个字符 */
	}
	printf("%s", ch);
	return 0;
}
  • 在洛谷测试需要修改scanf_s函数,上述代码在VS2019中可正常运行,如果不修改上述函数,可能会编译错误。
  • scanf_s在读入字符时需要填写第三个形参,填写内容是读入字符的最大长度。即上述《凯撒密码》中的scanf_s("%s", ch, 50),即最长读入字符串为50。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值