简单的填空
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
首先,主函数里用大括号定义了一个代码作用域,这说明里面的对象一出来就会被销毁。
再观察输出,不难发现调用A默认构造函数时,a+=2,b++,调用A的析构函数时,a--,b--。
|
|
简单的整数运算
描述
根据输出完善程序。
|
|
输入
$0 \sim 9$ 之间的两个整数 $m,n$ 。
|
|
输出
输出 $m \times n,$ 以及 $m \times n + m + n$ 。
|
|
Solution
重题,跟之前的题目比,此处仅需重载一个加号,详细思路见elainafan-从零开始的上机(6) 。
|
|
统计二进制里1的个数
描述
请你实现count函数。
该函数的功能为,给定一个正整数 $x(x < 2^{32})$ ,输出它的二进制表示里有多少个1。
|
|
输入
第一行一个正整数 $T$ ,表示数据组数。
接下来 $T$ 行,每行一个正整数,表示给定的 $x$ 。
|
|
输出
对于每组数据,输出一行一个数,表示 $x$ 二进制表示里1的个数。
|
|
Solution
事实上,在库函数中,这题是有popcount((unsigned)x)的直接用法的。
这里需要实现它,于是把x的二进制位逐一拆开计数即可。
|
|
attack
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
首先观察代码,首先这里需要一个Slime类的默认构造函数,它需要输出相关语句。
同时,由于它的析构函数最后被调用(由输出得到),因此它的析构函数是虚析构函数。
接着就看这个attack函数了,不难看出这里调用的是基类的attack函数,同时它调用了两个指针的name,由于它调用自身name调用的是PyroSlime类的,因此这里是多态,也就是Slime类内也要实现一个name虚函数,具体是啥没有关系。
|
|
奇怪的括号
描述
根据程序完善代码。
|
|
输入
|
|
输出
|
|
Solution
观察输出,不难发现需要实现传入一个整型的转换构造函数和传入两个整型的转换构造函数,且前者直接赋值,后者相乘。
由于有链式调用,因此重载()运算符时,需要返回f类型对象而非int,因此同样需要重载输出运算符。
|
|
MySet
描述
实现 set 的子类并重载成员函数 insert() 与 erase(),使得:
-
在插入重复元素时,会输出提示信息 “Error insert v”,其中 v 是插入的元素,并不执行插入操作。
-
在删除不存在的元素时,会输出提示信息 “Error erase v”,其中 v 是想要删除的元素,并不执行删除操作。
其余情况下行为与 set 行为完全相同。
|
|
输入
|
|
输出
|
|
Solution
这里已经显然是用模板类了。
根据题意,只需要实现找不到时输出错误,不然就执行原有操作,这里不多解释了,不难。
|
|
Singleton
描述
程序的输入为若干个整数,每次读取一个整数后,输出目前已经读入的整数数目,以及这些整数的和。
|
|
输入
若干行,每行一个整数。
|
|
输出
每次读取一个整数后,输出目前已经读入的整数数目,以及这些整数的和。
|
|
Solution
在私有变量中,有一个静态成员指针,初始化为空。
再看到主函数中,需要实现一个getInstance的静态成员函数,根据名字也不难猜到它能返回当前对象的指针。
而且,这道题肯定只需要创建一个类对象就可以完成,否则剩下的成员对象不好处理。
那么,这个函数的逻辑就是,如果instance为空就新建一个对象,否则返回instance指向的对象。
|
|
又又见模板
描述
根据输出完善程序。
|
|
输入
第一行是整数 $n$ ,表示有 $n$ 组数据。
每组数据有3行,第一行是10个整数,第二行是5个小数,第三行是4个不带空格的字符串,它们之间用空格分隔。
|
|
输出
先输出10个整数。
再连续输出两次5个小数的和 (不用考虑小数点后面几位,用cout直接输出即可)。
再连续输出两次4个字符串连在一起的字符串。
|
|
Solution
做这种题有个小技巧:外部可以填空的,说明类外面一般有东西要写。
观察代码,不难发现这里需要使用模板类,第二个参数默认为int。
并且,它为了存数组,肯定是需要用一个T*指针,在构造函数中向堆取空间,析构函数中释放空间,并且调用sum的时候实现题目操作。
同时,观察到需要重载输出运算符,以及类外面要写一个print_sum函数,它也是模板函数,进行累加即可。
|
|
怎么又是CArray3d三维数组模板类
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
重题,这题无非只是需要多重载一个加号而已,不是啥难事,直接将一个指针所有元素累加到另一个指针对应的空间上即可。
其他思路见elainafan-从零开始的上机(7) 。
|
|
Myaccumulate
描述
程序填空输出指定结果,要求实现类似accumulate的模板。
|
|
输入
第一行是数组长度 $n (5 < n < 100)$ 。
接下来 $n$ 行,每行一个小于等于1000的正整数。
再接下来 $n$ 行,每行一个非空字符串,字符串均由小写字母组成,长度不超过 100。
|
|
输出
|
|
Solution
首先观察代码,很显然这里的Muaccumalate需要分别以模板函数和模板类仿函数的形式实现。
然后就不难了,只需要跟之前一样就行,注意这里操作函数也需要作为一个模板类对象传入。
|
|
Option
描述
Option 是个有趣的类,它可以保存一个正常的值,也可以是空值(None)。
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
观察代码,首先发现这里Option是一个模板类,同时它有默认构造函数和转换构造函数(两种,一种传入TNone,另一种传入T)。
可以用一个bool型变量表示是否被赋值,然后可以用一个T型变量表示被赋的值。
同时,可以看到需要实现Option类到bool类的强制类型转换函数,由于const变量只能调用const函数,所以要重载两个。
随后,可以实现has_value和value函数,返回是否被赋值和被赋的值。
再往下看,由于*b+=10,需要重载*,使其返回T&对象(因为有修改)。
此时还有报错,看到这里有**y,但是如上文所说,const变量只能调用const函数,因此还需要重载const的*。
注意,这里**其实就是返回T&,这点通过链式调用可以看出,同时题目中的赋值都是默认传值,可以不用重载采取编译器默认行为。
|
|
学生排名
描述
输入学生和他们的分数,输出他们的排名及对应分数。
|
|
输入
有多组数据,第一行是数据组数 $t(t \leq 5)$ 。
对每组数据:
第一行为整数 $n(n \leq 100000)$ 。
接下来的 $n$ 行每行开头是一个字符串 $s$ ,代表学生名字,后面是他们的分数 $g(0 \leq g \leq 100)$ ,学生名字长度在 $0 \sim 20$ 之间。如果有重复的名字输入那么只保留第一个出现的名字对应的所有信息。
|
|
输出
对每组输入数据,排序后输出学生姓名和成绩。排序规则:按照分数从大到小排序,分数相同的学生按照名字长度从小到大输出,名字长度再相同就按照字典序。
|
|
Solution
跟上次那道题一样,但是不要看错题目。这道题是,如果有重复的名字输入,那么只保留第一个出现的名字对应的所有信息,上次那个题是,如果一个人出现如果两个同样名字的人考了同样的分数,那么保留一个就可以。意思是本题不允许名字相同的存在,上题允许名字相同但分数不同的人存在。
思考一下这道题的思路,首先需要实现的就是重载输入和输出运算符,不过先别着急,先思考一下结构吧。
由于需要先按照分数排,再按照人名排,因此考虑建立同分数到一堆人的映射,这就是一个map,再用一个set存储人名与人名长度的pair并自动排序,由于这道题不是直接比较字符串而是先比较字符串长度。
然后,还需要用一个map或者set记录是否输入过某个人名,输入的时候查找一下,若没有则输入,否则不作处理。
输出的时候直接倒序遍历map,并输出其中的人名即可,分数就是map的键。
|
|
满足条件的数
描述
请你实现print函数。
该函数的功能为,给定一个正整数x,从小到大输出所有非负整数 $y$ 满足 $x & y = y$。 正整数 $x < 2^{32}$ ,并且满足二进制表示里最多存在 $10$ 个1。
|
|
输入
第一行一个正整数 $T$ ,表示数据组数。
接下来 $T$ 行,每行一个正整数,表示给定的 $x$ 。
|
|
输出
对于每组数据,输出若干行,每行一个数。表示从小到大的满足条件的 $y$ 。
|
|
Solution
这道题是位运算里面一个很常见的trick,从集合的角度看就是枚举子集。
具体证明过程及思考可以见下方图片讲解。

好了,这里是从大到小,那么怎么办?
很简单,由于一个子集的补集也是子集,那么从大到小,并且取异或即可。
|
|
这是白给的题
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
确实是白给的题,直接在默认构造函数里输出即可。
|
|
这可不是多态
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
就如题目所说,这可不是多态,连派生都没有,自然不是多态。
在前面已经讲解过,const变量只能调用const成员函数,因此这里需要一个const的printV。
观察输出,发现非const变量输出的都是2,因此重载一个非const的printV,输出v+1即可。
|
|
该调用哪个函数
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
这里可以看到,首先声明四个A变量,都是调用默认构造函数,此时静态成员变量total是4,说明默认构造函数加一。
随后,又声明了四个A变量,一个调用传入一个整型的转换构造函数,一个调用传入两个整型的转换构造函数(注意这里是直接构造而不是先构造再拷贝),两个调用默认构造函数,结果为8,说明也是都加一。
接着使用拷贝构造函数,也还是加一。
最后,析构,不难发现这里减一了,于是完成。
|
|
Base和Derived
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
观察代码,不难发现Base类应该有一个静态成员函数print_total,同时它也应该有一个静态成员变量gem(因为根据输出它被多次打印)。
随后可以发现,需要实现Base类的析构和默认构造函数,根据顺序可知,这里的析构函数不是虚析构函数。
再看daily,这里B->daily调用时,gem增加了150,说明是多态,因此Base中的daily是虚函数。
|
|
排名学生
描述
根据输出完善程序。
|
|
输入
第一行为一个整数 $n(n \leq 1000000)$ 。
接下来n行每行开头是一个字符串 $s$ ,代表学生名字,后面是他们的分数 $g(0 \leq g \leq 100)$ ,学生名字长度在 $1 \sim 5$之间。
|
|
输出
对输入分数按照从大到小的顺序进行排序,每行输出一个分数,并在分数后面输出每个分数对应的名字,名字的顺序按照字典序从小到大排列。每个名字在每个分数中只能出现一次,即如果有两个同样名字的人考了同样的分数那么只保留一个即可。
|
|
Solution
跟上面那道题差不多,不一样的地方已经解释过了。
这道题比较简单,直接使用字典序,因此只需要map建立分数到人名集合的映射,再用vector<string>存人名(输出的时候在排序,因为没给set),最后倒序遍历map的迭代器即可。
|
|
求和
描述
完成代码填空。括号运算符实现一个求和的功能。每次调用括号运算符时进行计数。
|
|
输入
|
|
输出
|
|
Solution
重题,甚至比之前讲的题简单,具体解析见elainafan-从零开始的上机(8) 。
诡异的求和
描述
请补充下列代码,使其可以输出输入所有数字的和。
|
|
输入
第一行若干个整数。保证整数个数不超过 10,每个整数的绝对值大小不超过 10。
|
|
输出
输出一个整数,表示输入所有数字的和。
|
|
Solution
不是很理解诡异在哪。
由于只输出一个值,因此输出运算符不具备输出的能力,它的功能只有加法。
最后要输出?那么,直接在析构函数里输出即可。
|
|
神奇的模板类
描述
读入一个整数和一个字符串,输出该整数、该整数的两倍、该字符串、该字符串的两倍 (即字符串重复两次)。
|
|
输入
多组数据,第一行是一个整数 $m$ ,表示有 $m$ 组数据。
此后有 $n$ 行,每组数据占一行,每行有一个整数和一个字符串,中间用空格隔开。
|
|
输出
对于每组数据,输出四行,分别为该整数、该整数的两倍、该字符串、该字符串的两倍(即字符串重复两次)。
|
|
Solution
这道题再次说明了,如果类外还有填空,那么大概率确实要在类外写一些东西。
观察代码和输出,不难发现MyTemplateClass类到T的强制转换函数保持原样,而在print中会变为两倍。
也就是说,只需要重载MyTemplateClass中的输出运算符,让它加一下就可以。
然后看MyString类,由于需要加,它要重载一下加号,同时输出的时候,是以MytemplateClass->MyString的形式输出的,因此也要重载输出运算符。
|
|
麻烦的位运算
描述
写出函数中缺失的部分,使得函数返回值为一个整数, 该整数的第 $i$ 位为 1 当且仅当 $n$ 的右边 i 位均为 1。
请使用 一行代码 补全bitManipulation4函数使得程序能达到上述的功能。
|
|
输入
第一行是整数 $t (t \leq 20)$,表示测试组数。
每组测试数据包含一行,是一个整数 $n$ 。
|
|
输出
对每组输入数据,输出一个整数,其第 $i$ 位为 1 当且仅当 $n$ 的右边 i 位均为 1。
|
|
Solution
这道题给大家一个启发:看到位运算,需要有一个lowbit的思路。
所谓lowbit,就是求x的最低位1,例如lowbit(12)=4,它的通常形式是x&(-x)。
然后,还是没思路,为啥不打个表?竞赛位运算中打表是很常见的喔~
不过打表有点赖了,这里先考虑怎么求解,从题目中不难看出这个整数的右侧1也是连续的,假设 $n$ 的后面连续位都是1,那么 $lowbit(n+1)$ 就是 $n$ 的右侧第一个零所在的位置,再减一,就是 $n$ 的右侧连续1,也就是答案。
|
|
排序
描述
对于数组里的每个元素 $a$ 按照 $a \times x \mathrm{MOD} \ p$ 为第一关键字, $a$ 为第二关键字排序。
|
|
输入
一行,2个整数 $x, p$ 。
|
|
输出
按照 $a \times x \mathrm{MOD} \ p$ 为第一关键字 $a$ 为第二关键字排序后的结果。
|
|
Solution
其实,这里不需要理会提示的信息,因此笔者直接删掉了。
记住sort可以传lambda表达式,这在程设学习还是竞赛编程中都是强大的工具。
|
|
网络连接计数
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
首先,观察代码,不难发现这里每台电脑的连接和断开是独立的,即不存在间接连接的电脑因为直接连接的电脑断了,自己也断了的情况。这可以用并查集理解,每台电脑都直接连到根了。
于是,由于每次连上都要对Network进行操作,因此需要存一个指向Network的指针,同时还要存一个bool变量表示是否连上了。
随后,观察主函数,需要写一个转换构造函数和一个拷贝构造函数,还要实现Connect和disconnect函数。
再往下看,需要重载一个赋值运算符和实现析构函数。
其实上面的逻辑都很清楚,要注意的是,在处理Newwork相关的时候要注意当前是否连上了,如果没连上对空指针操作会报错。
|
|
更强的卷王查询系统
描述
古人云:“开卷有益”。但是,著名的社会学家小明认为内卷是有害的,并且他正在写一篇与P大内卷现状有关的论文,需要选取具有代表性的“卷王”们进行访谈。小明现在搞到了一份长长的成绩单,拜托你写个程序,帮他找出成绩单上的“卷王”们。
“卷王”的定义是:给定一组课程,这组课程全部上过的学生中,这组课程平均分最高的学生。小明已经通过复杂的数据挖掘手段得到了要分析的课程组,现在需要你按照上述定义,对每组课程找出那个真正的“卷王”。
输入
第 $1$ 行:一个整数 $n(1 \leq n \leq 100000)$ 。
第 $2 \sim (n+1)$ 行:每行有用空格分隔的两个字符串和一个整数,前两个字符串分别代表课程名和学生名,最后一个整数代表这个学生在此课程中取得的成绩。输入保证课程名和学生名只包含字母,且一个学生在一个课程中不会出现两次成绩。输入保证课程数量不超过 $1000$ 门,且每门课的学生数量不超过 $100$ 人。输入不保证任何顺序。
第 $n+2$ 行:一个整数 $m(1 \leq m \leq 10)$ ,代表查询的个数,即课程组的组数。
接下来 $m$ 行:每行是一个课程组,第一个整数 $k(1 \leq k \leq 100)$代表该组课程的数量,后面有 $k$ 个字符串,表示 $k$ 个课程名。整数 $k$ 和字符串之间均用一个空格分隔。数据保证课程名一定在之前出现过。
|
|
输出
输出为 $m$ 行,每行对应一个课程组,输出该组课程平均分最高的学生,只考虑学过该组全部课程的学生。如果平均分最高的学生多于一个,输出姓名按英文词典排序最靠前的学生。数据保证对每组课程,都存在学过该组所有课程的学生。
|
|
Solution
首先要注意的是,这道题好像加上一个find的复杂度就会被卡,因此应该找到正解,笔者当时做的时候好像就被卡了。
先思考,要用什么样的数据结构维护?
一种思路是,先建立人到他所学的课程的映射,然后再套一层这个课程到分数的映射,每次查一个课程组的时候一个一个人查,这种思路好像被卡了。
于是考虑另一种思路,先建立某门课程到某个人的映射,然后再套一层这个人到分数的映射,接着维护一个人到他所学课程课程的映射,每次一个人一个人查,如果查到再取出分数并存入暂存区(因为后续需要判断),没查到直接跳过。
最后,让暂存区排个序输出人名,即可。
|
|