本题是浙江理工大学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成员群中提问哦!

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

  1. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++85——完美数

    本题是浙江理工大学ACM入队200题第八套中的L题 我们先来看一下这题的题面. 题面 题目描述 任何一个自然数的约数中都有1和它本身,我们把小于它本身的因数叫做这个自然数的真约数. 如6的所有真约数是 ...

  2. 「浙江理工大学ACM入队200题系列」问题 K: 零基础学C/C++84——奇偶ASCII值判断

    本题是浙江理工大学ACM入队200题第八套中的K题 我们先来看一下这题的题面. 题面 题目描述 任意输入一个字符,判断其ASCII是否是奇数,若是,输出YES,否则,输出NO; 例如,字符A的ASCI ...

  3. 「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积

    本题是浙江理工大学ACM入队200题第八套中的E题 我们先来看一下这题的题面. 题面 输入 输入数据包含多个测试实例,每个测试实例占一行,每行的第一个数为n,表示本组数据一共有n个,接着是n个整数,你 ...

  4. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++52——计算数列和2/1,3/2,5/3,8/5......

    本题是浙江理工大学ACM入队200题第五套中的L题 我们先来看一下这题的题面. 题面 题目描述 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13,-- 计算这个数列的前n项和.注意: ...

  5. 「浙江理工大学ACM入队200题系列」问题 F: 零基础学C/C++39——求方程的解

    本题是浙江理工大学ACM入队200题第四套中的F题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  6. 「浙江理工大学ACM入队200题系列」问题 A: 零基础学C/C++34—— 3个数比较大小(冒泡排序与选择排序算法)

    本题是浙江理工大学ACM入队200题第四套中的A题,同时给出了冒泡排序和选择排序算法 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习 ...

  7. 「浙江理工大学ACM入队200题系列」问题 H: 零基础学C/C++18——三位数反转

    本题是浙江理工大学ACM入队200题第二套中的H题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  8. 「浙江理工大学ACM入队200题系列」问题 B: 零基础学C/C++12——求平均值

    本题是浙江理工大学ACM入队200题第二套中的B题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  9. [Python] 文科生零基础学编程系列二——数据类型、变量、常量的基础概念

    上一篇:[Python] 文科生零基础学编程系列--对象.集合.属性.方法的基本定义 下一篇: (仍先以最简单的Excel的VBA为例,语法与Python不同,但概念和逻辑需要理解透彻) p.p1 { ...

随机推荐

  1. HEXO-admin安装和使用(汉化版)

    hi,大家好,我是KINGWDY,众所周知我用的是hexo,写博文首先要在终端输入hexo n xxxxx,然后打开MWeb PRO开始写md,但是,这很麻烦,就在我一筹莫展之际,我看到了这篇博文-- ...

  2. 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。

    有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...

  3. UOJ#XX A+B Problem (罔烙硫)

    题面 背景 题目描述 从前有个 n n n 个方格排成一行,从左至右依此编号为 1 , 2 , ⋯ , n 1,2,⋯,n 1,2,⋯,n. 有一天思考熊想给这 n n n 个方格染上黑白两色. 第 ...

  4. 诺塔斯读写卡QT SDK笔记

    卡片操作函数调用 寻卡: Request --> LotusCardRequest 防撞处理: Anticollission --> LotusCardAnticoll 选卡: Selec ...

  5. fastadmin后台分页设置显示方法

    ​ 1.参照日志列表的分页(后台代码都有) 2.修改默认分页配置,在初始化里面加上: pageList: [5,10,'all'], 3.显示列表: [$where, $sort, $order, $ ...

  6. 如何为 SAST 工具设置误报基准?

    许多 SAST 工具都无法避免误报的问题.这些工具经常报告一些实际不存在的漏洞,这种不准确性让安全团队耗费大量时间来对误报进行分类和处理,这时设置误报基准就显得十分必要. 通过设置误报基准,安全团队可 ...

  7. 《Win10——如何进入高级启动选项》

    Win10--如何进入高级启动选项       第一种方法: 管理员命令提示符输入如下代码,自动重启并进入高级启动选项. shutdown /r /o /f /t 00     第二种方法: 1. 管 ...

  8. thinkphp5.1发送邮件的方法

    1.安装插件 composer require phpmailer/phpmailer 2.application下的common.php文件里加上一下代码,可自己根据需求稍加修改,我用的是验证码 u ...

  9. 【学习笔记】循环神经网络(RNN)

    前言 多方寻找视频于博客.学习笔记,依然不能完全熟悉RNN,因此决定还是回到书本(<神经网络与深度学习>第六章),一点点把啃下来,因为这一章对于整个NLP学习十分重要,我想打好基础. 当然 ...

  10. Prometheus Operator 对接 Thanos

    文章转载自:https://jishuin.proginn.com/p/763bfbd56ae4 使用 Prometheus Operator 来进行监控,在 Prometheus 高可用的章节中也手 ...