首页 > 编程语言 >「浙江理工大学ACM入队200题系列」问题 J: 零基础学C/C++83——宁宁的奥数路

「浙江理工大学ACM入队200题系列」问题 J: 零基础学C/C++83——宁宁的奥数路

时间:2022-09-26 23:23:56浏览次数:85  
标签:200 遍历 下标 数字 10 重复 ACM 入队 我们

本题是浙江理工大学ACM入队200题第八套中的J题

我们先来看一下这题的题面.

题面

题目描述

宁宁参加奥数班,他遇到的第一个问题是这样的:口口口+口口口=口口口,宁宁需要将1~9 九个数分别填进对应的空格内,使等式成立。现在宁宁填了一个算式,你能帮他验证是否正确么?

输入

输入为多组测试数据。

分别输入三个三位数,依次表示等式里的三个数。

输出

如果等式成立,输出:YES!,否则输出:NO!

样例输入

173 286 459

样例输出

YES!


题目分析与常见错误思路

这题很多朋友都想当然地以为只需要判断等式是否成立即可,都选择性的忽视了题目中明确写出的要求:将1~9九个数分别填进对应的空格内.
所以我们需要额外实现判断没有使用重复的数.

解决方案

如何实现捏?首先我们需要依次取出每个数的各个十进制位,这里我已经有一篇博客给出明确的方法介绍了,不清楚的可以去看看(点我看鸭),这里不多赘述了.
接下来困住大多数朋友的都是判断重复了,很多朋友对此毫无思路.
我们先来想想我们人脑是怎么判断有没有数字重复的呢?打个比方我们要在一组数字中找第一个数是否重复,那么当我们看到这组数字中的一个数后,我们会接着往后去看有没有第二个这个数出现,如果有就是重复了,否则就是没有.
我们是否也可以这样实现我们这里判断重复的代码捏?答案是可行的,我们可以把这三个数的每个位合起来看成一个"数组"中的元素,然后从左到右遍历这个"数组",再对于每一个遍历到的数之后的数进行一次遍历,看看其中是否有和这个数相等的数存在.不过这种思路遍历次数较多,比较接近暴力算法,时间复杂度很高(可以理解成代码运行的速度很慢),属于一种无解算法.所以我们需要寻找一个更好的算法.(这种思路的代码就不贴了,想练代码可以自己写写试试,交上去不清楚会不会时间超限,没试过)
我们前面的算法慢在哪呢?慢在我们每次都对遍历到的数再启动了一次遍历,这使得我们遍历的次数过多.而且每次遍历都是在重复遍历这些数.我们是否可以避免这些重复的操作,以此提高速度呢?答案是可行的.
那如何避免重复操作呢?我们可以对遍历到的数进行一次记录,记录什么呢?我们上面这样判断的本质其实是在看有没有哪个数字重复出现了两次及以上,所以我们就记录每个数字出现了几次即可,这样仅通过一次遍历,我们便得到了可以判断是否有重复数字的数据,大大减少了遍历的次数.这其实便是所谓的用空间换时间的技巧.
那用什么记录呢?我们目前会的数据结构非常少,基本只有数组.那能否通过数组来记录呢?当前可以!这里就需要用到另一个常用的技巧了.我们希望记录的形式是"数字:数字出现次数"这样形式的一个对子,并且我们可以通过数字来访问到这个数字出现的次数.这个对子和数学上的映射很像.而这个映射完全可以由数组来完成,因为数组本身的随机访问也可以看成一种映射.
我们知道,当我们给定数组中某个元素的下标,我们即可得到这个下标对应的那个元素,这是一种现成的映射.那我们自然也可以把数字作为下标,把数字出现的次数作为下标对应的元素.即,我们使用一个长度为10的数组,在其下标1到9的各个元素中存储1到9各个数字出现的次数.这是一种很重要的编程思想,叫,是不是很形象鸭.如果有一定数据结构基础的朋友应该会马上联想到哈希表,不过这题没必要(其实下面的思路广泛地讲也是一种哈希表).

参考代码

下面给出了我自己做这道题时候的完整代码:
(仅作为参考,一定要自己写一下奥,作弊没意思,害人又害己)

#include <stdio.h>
#include <string.h>
// 数组最好定义在main外面(以后你们会知道为啥的)
int num[10]; // 作为桶,下标所对应的元素储存着下标这个数字出现的次数,由此形成一个一一映射

int main()
{
	int a, b, c;
	while (scanf("%d%d%d", &a, &b, &c) != EOF)
	{
		if (a + b != c) // 如果不满足加法式,直接输出然后输入下一组
		{
			printf("NO!\n");
			continue; // 跳过本组处理,开始下一组的输入
		}
		for (int i = 0; i < 3; i++) // 各个数字依次取出各个位
		{
			num[a % 10]++; // 下标为该数字的元素储存着该数字出现的次数,将该数字的出现次数加一
			a /= 10;
			num[b % 10]++;
			b /= 10;
			num[c % 10]++;
			c /= 10;
		}
		int i; // 为了判断for是否正常退出这里我i定义在外面,也可以在单独搞一个变量来记录是否有数重复
		for (i = 1; i < 9; i++)
		{
			if (num[i] > 1) // 如果一个数字出现了两次
			{
				printf("NO!\n");
				break; // 直接跳出这个for循环,不用再找有没有重复了(只要一组重复就不满足了)
			}
		}
		if (i == 9) // for正常退出时i应为9,如果不为9就是被break强行退出了
		{
			printf("YES!\n");
		}
		memset(num, 0, sizeof(num)); // 桶初始化(别忘了鸭!)如果不会用memset也可以考虑直接写一个for循环把每一元素设置为0
	}
	return 0;
}

"正是我们每天反复做的事情,最终造就了我们,优秀不是一种行为,而是一种习惯" ---亚里士多德

这篇题解就到这里了,各位朋友如果有问题欢迎到acm成员群中提问哦!

标签:200,遍历,下标,数字,10,重复,ACM,入队,我们
From: https://www.cnblogs.com/gemini-star/p/zstuACM200_8J.html

相关文章

  • [SDOI2008]Sue的小球
    做题时间:2022.9.26\(【题目描述】\)一个平面直角坐标系中有\(N\)个小球,第\(i\)个小球初始时位于\((x_i,y_i)\),有一个速度\(v_i\),每一秒会沿着\(y\)轴竖直想下掉......
  • 华东师范大学算法课ACM——框体排列
    框体排列单点限制:1.0sec内存限制:512MB数轴上有n个点,每个点有一个坐标ai。现在需要用数个宽度为k的框体覆盖数轴上全部n个点,求出最少需要的框体数量。输入格式......
  • luogu P2233 [HNOI2002]公交车路线
    [HNOI2002]公交车路线题目描述在长沙城新建的环城公路上一共有\(8\)个公交站,分别为A、B、C、D、E、F、G、H。公共汽车只能够在相邻的两个公交站之间运行,因此你从某一......
  • luogu P1772 [ZJOI2006] 物流运输 (dp, 最短路)
    https://www.luogu.com.cn/problem/P1772虽然是图论背景,但是1-n天之间是线性关系。没法贪心决策,考虑dp:我本来写的dp是i-1转移到i,但是这样没法处理哪一天能走哪些最短路......
  • SF2006-ASEMI半塑封快恢复二极管SF2006
    编辑:llSF2006-ASEMI半塑封快恢复二极管SF2006型号:SF2006品牌:ASEMI封装:TO-220AB正向电流:20A反向电压:600V引线数量:3芯片个数:2芯片尺寸:110MIL漏电流:20ua恢复时间:35......
  • 2000-2023-1 20221302《计算机基础与程序设计》第四周学习总结
    2022-2023-120221401《计算机基础与程序设计》第四周学习总结作业信息班级链接:https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP作业要求:https://www.cnblogs.c......
  • 2000-2023-1 20221313《计算机基础与程序设计》第四周学习总结
    2022-2023-120221300《计算机基础与程序设计》第四周学习总结作业信息这个作业属于哪个课程<班级的链接>https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP......
  • 「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积
    本题是浙江理工大学ACM入队200题第七套中的E题(大概)我们先来看一下这题的题面.题面输入输入数据包含多个测试实例,每个测试实例占一行,每行的第一个数为n,表示本组数据......
  • GoLang之ACM控制台输入输出
    转自:https://blog.csdn.net/weixin_52690231/article/details/125436414    ......
  • 200天1000题 (DAY 8)
    200天1000题(DAY8)目前总题数:36目前CF分数:1336(+11)今天打了一下CFRound#822(DIV2)手速比以前快,过了3个题,D想到一个双指针贪心的写法,但实现出来的代码有漏洞,疯狂WA......