LuoguB2001 入门测试题目 题解
Update
- \(\texttt{2021.7.3}\) 经测试,本题 \(a,b\) 范围在 long long,对代码进行了修改,并修改一些笔误,更新了数据范围。
- \(\texttt{2021.7.5}\) 应评论区要求,加上了 long (int) 的数据范围,并修改了原题中 \(a,b\) 的数据范围。
- \(\texttt{2021.7.16}\) 去掉了数据范围中的绝对值符号,感谢 @Implicit 的提醒。另外对原文章中的一些错误进行了修改。但之后题解被无意义内容打回了,一开始决定将本题解里头涉及到的语言知识放入一个剪贴板中,并对整体编排做了较多修改,后经 WYXkk 和 XYY1411 的建议作了一些知识性方面和排版方面的修改,并重新将剪贴板的内容放在代码后面以作补充性讲解。感谢各位的建议!
Content
给定 \(a,b\),求 \(a+b\)。
数据范围:\(1\leqslant a,b\leqslant4\times10^{18}\)。
Solution & Code
本题解仅适用于 C++ 选手。
这道题可谓是 C++ 中最基础的题目之一,先上两份代码:
1
#include <cstdio>
using namespace std;
int main() {
long long a, b;
scanf("%lld%lld", &a, &b);
printf("%lld", a + b);
return 0;
}
2
#include <iostream>
using namespace std;
int main() {
long long a, b;
cin >> a >> b;
cout << a + b;
return 0;
}
那么这一行行语句都代表着什么呢?这两个程序如何达到相同的效果呢?接下来就对此进行详细讲解。当然,初学者如果看不懂这些东西其实也无关紧要,因为这些都将在我们今后的学习中逐渐了解。
Part 1 基础语言知识
首先我们要知道程序最开始的 #include <xx>
是什么意思,其实就是把 C++ 中的一些头文件库给包括进来,这里给几个常见的头文件库:
<cstdio> //输入/输出(这是注释)
<iostream> //输入/输出流
<string> //字符串类
<cstring> //同上
<cmath> //包含了许多实用的数学函数,例如 sin(),cos(),tan(),sqrt(),pow() 等
<algorithm> //STL 通用算法
<stack> //STL 栈容器
<queue> //STL 队列容器
<deque> //STL 双端队列容器
<map> //STL 映射容器
<vector> //STL 动态数组容器
/*
这是多行注释。
STL 可以很方便的简化我们的代码,但是常数很大,
有时运行起来很慢,所以建议知道如何手写。
这将是我们以后学习的内容,现在不知道并无大碍。
*/
对于这道基础题目,我们只需要包含 cstdio
库或者 iostream
库,因为这道题目只需要我们输出 \(a+b\) 的结果。
然后就是数据类型的问题。我们先不妨认识一些常用的数据类型。下图的这些数据类型(C++ 其他常用数据类型除外)统称为预定义类型,也就是说,这些数据类型是 C++ 已经为你准备好的。
另外,我们还将学到数组、结构体 struct 联合体 union、枚举 enum 等其他比较灵活的类型,这些数据类型统称为自定义数据类型。
那我们如何选择数据类型呢?这得要从数据范围来决定。以下给出了常用数据类型在通常情况下的范围(建议去题解页面查看),对于今后做题时变量应该如何选择数据类型有很大的作用:
数据类型 | 范围 |
---|---|
char | \([-128,127]\) 或 \([0,255]\),在系统字节不是 8 位的情况下可以达到更大的数据范围 |
unsigned char | \([0,255]\),在系统字节不是 8 位的情况下可以达到更大的数据范围 |
signed char | \([-128,127]\),在系统字节不是 8 位的情况下可以达到更大的数据范围 |
int/long (int) | 通常情况下为 \([-2147483648,2147483647]\)(或者说 \([-2^{31},2^{31}-1]\)),但 int 只保证 \([-32768,32767]\)(或者说 \([-2^{15},2^{15}-1]\)) |
unsigned int | \([0,4294967295]\)(或者说 \([0,2^{32}-1]\)) |
signed int | 同 int |
short int | 至少 \([-32768,32767]\)(或者说 \([-2^{15},2^{15}-1]\)),但可以达到更大的数据范围 |
unsigned short int | \([0,65535]\)(或者说 \([0,2^{16}-1]\)) |
signed short int | 同 short int |
long long (int) | 通常情况下为 \([-9223372036854775808,9223372036854775807]\)(或者说 \([-2^{63},2^{63}-1]\)),但在 C++11 开始才保证至少是这个数据范围 |
signed long long (int) | 同 long long (int) |
unsigned long long (int) | \([0,18446744073709551615]\)(或者说 \([0,2^{64}-1]\)) |
float | \([1.17\times 10^{-38},3.40\times 10^{38}]\)(约数,来源于 IEEE-754 标准) |
double | \([2.23\times 10^{-308},1.80\times 10^{308}]\)(约数,来源于 IEEE-754 标准) |
long double | \([3.36\times 10^{-4932},1.19\times 10^{4932}]\)(约数,一说和 double 范围相等) |
关于 long double 的一些说明:long double 是一种扩展精度浮点类型,不一定映射到 IEEE-754 所强制的类型。在 x86 和 x86-64 架构上通常为 80 位 x87 浮点类型。表格中采取的 long double 的数据范围来源于这篇文章。
然后就是函数了,函数有头文件库里面自带的,也有你需要在程序中自己写出来的。比如说 sin()
、sort()
这些就是 C++ 的头文件库里面自带的,而通常程序中有些函数需要你自己写出来。在需要自己写出来的函数中,最重要也是最必不可少的就是 main()
函数。一般在算法竞赛中,它的类型通常是 int
,而且最后通常会要求你写 return 0;
,具体的意义不做赘述。除了 main()
函数和头文件库里面自带的函数外,你也可以自己写一些其他的函数,达到精简代码的效果。
然后就是输入和输出了,如果你调用的是 cstdio
库的话,它里头包含的最常用的输入函数就是 scanf()
。
scanf()
函数返回成功读入的数据项数,读入数据时遇到了“文件结束”则返回 EOF
(End of file,即文件结尾)。例如,对于这道题,我们需要读入 \(a,b\),就用 scanf("%d%d", &a, &b)
,其中 %d
是 int
这个数据类型在 scanf()
函数中的格式,其它的格式还有 %f
\(\rightarrow\) float
、%lf
\(\rightarrow\) double
、%lld
\(\rightarrow\) long long
等。另外,scanf()
函数还有一个强大的功能,就是你可以用 scanf()
按照某一个特定的格式读入数据,例如,你想要按照 hh:mm
的个数读入 \(hh\) 和 \(mm\),就可以用 scanf("%d:%d", &hh, &mm)
。注意,如果是整形类型的话,变量前的 &
必不可少。
为什么要加一个 &
号?这里不多做讲述,感兴趣的各位可以去看这个剪贴板。
如果你调用的是 iostream
库的话,它里头包含的输入流(注意!并不是函数)是 cin
。你就把输入流想象成一条河流,源源不断地输入数据就行,这里就不给出严格定义了。在 cin
中,每一个输入的数据以 >>
号连接,前面并不需要加 &
。
然后就是输出了,输出其实和输入很类似,所以这里仅作简略讲解。
scanf()
函数对应的是 printf()
函数,返回成功输出的数据项数。按照和 scanf()
一样的格式,同样也可以按照某个特定格式输出数据,例如 %8d
就可以讲一个整数按以 \(8\) 为宽度右对齐输出(详情请见 B2004),%02d
就可以将一个整数输出,并且如果不足两位的话会向前补前导零。例如 printf("%8d, %02d", 2, 2)
对应的输出结果就是:
2, 02
另外如果题目要求保留一位小数或者你的输出应与答案的相对误差不超过 \(10^{-3}\) 等要求,那么我们就可以利用 printf 中的按位输出的格式 %.xlf
或者 %.xf
输出(其中 x
里面是数字),例如保留一位小数就可以写成 printf("%.1lf", x);
。
输入流 cin
自然也就对应输出流 cout
,你同样也可以将其想象成一条源源不断地输出数据的河流。但请注意,在 cout
中,每一个输出的数据以 <<
连接!!!除了这个地方和 cin
不同之外,其他的都和 cin
并无差异。
那么 cout
是否也可以做到按位输出或者按某个特定宽度右对齐输出呢?答案是肯定的,但由于版面原因,这里并不做介绍,感兴趣的各位可以直接上网查询。
Part 2 本题你需要了解的一些东西
对于这道题目来说,\(1\leqslant a,b\leqslant4\times10^{18}\),因此我们用 long long/signed long long 数据类型。因为在算法竞赛中 long long 常用些,所以这里的代码也用的是 long long 这个数据类型。
接下来就是如何表示 \(a+b\) 了,这里就要讲到 C++ 中的数字运算符。首先就是最基本的加减乘除,它在 C++ 中分别表示为 +
、-
、*
、/
,但请注意,/
在 C++ 中的定义并不完全等同于我们平常的四则运算中的除法,如果两边都是整型变量,在 C++ 中,/
默认为整除。那么有没有办法可以让它变成我们平常的除法呢?答案是肯定的,让 /
两边中的一个或者两个数变成浮点型变量(\(\texttt{float}\)、\(\texttt{double}\)、\(\texttt{long double}\) 等),就可以让 /
的结果变为实际结果而不是整除后的结果了。例如,\(\texttt{5/6}\) 在 C++ 中的结果是 \(0\),但如果你将其变成 \(\texttt{5.0/6}\) 或 \(\texttt{5/6.0}\) 或 \(\texttt{5.0/6.0}\),那么 C++ 就会输出其正确的结果 \(\texttt{0.8333\dots}\)(具体输出多少位取决于题目具体要求)。那么它的运算顺序是怎样的呢?如果仅限于加减乘除的话,它的运算顺序和平常的四则运算顺序是一样的:先乘除后加减,有括号先算括号里面的算式。只不过 C++ 里面提供运算的符号仅为小括号 ()
罢了。
那么我们对于程序做了深入的剖析,想必大家都已经领会到 C++ 的语言魅力了。
Notice
本文章引用了一些网络上的内容,由于作者能力有限,可能仍不免有诸多错误,欢迎各位在评论区指出,作者将定期订正这些错误。
同时,如果您认为这篇文章侵犯了你的著作权,请及时和作者联系换下。
另外,这篇文章期间也经过了一些不小的修改,感谢 WYXkk、XYY1411、Implicit 等各路神仙对这篇文章提出的宝贵的修改建议,才使得这篇文章经过不断完善变得更加充实和严谨!
祝各位的信息之路愉快而又充实!
LuoguB2001 入门测试题目 题解的更多相关文章
- ZROI 部分题目题解
ZROI 部分题目题解 335 首先发现一个性质: 对于最短的边而言,所有点的路径如果经过了这条边,那么路径的权值就是这条边的边权(废话) 那么我们把最短的边拎出来,可以发现,博物馆确定时,每个点按照 ...
- PTA|团体程序设计天梯赛-练习题目题解锦集(C/C++)(持续更新中……)
PTA|团体程序设计天梯赛-练习题目题解锦集(持续更新中) 实现语言:C/C++: 欢迎各位看官交流讨论.指导题解错误:或者分享更快的方法!! 题目链接:https://pintia.cn/ ...
- 一套很有意思的C语言测试题目
网络上逛博客,发现了一套很有意思的测试题目: https://kobes.ca/ 大家有兴趣可以做一下,考一些关于C语言使用的细节: 中文翻译参考: https://www.cnblogs.com/l ...
- 软件测试入门——测试模型(V型 W型 H型)
软件测试工程师称为“QA”,质量保证者——这是入门的第一点要学习的. 首先看基本的测试模型 1.“V”型 特点:[活动串行]这是一种古老的瀑布模型,反映了实际和测试之间的关系. 局限:仅仅把测试过程作 ...
- chd校内选拔赛题目+题解
题目链接 A. Currency System in Geraldion 有1时,所有大于等于1的数都可由1组成.没有1时,最小不幸的数就是1. #include<iostream> ...
- Tarjan & LCA 套题题目题解
刷题之前来几套LCA的末班 对于题目 HDU 2586 How far away 2份在线模板第一份倍增,倍增还是比较好理解的 #include <map> #include <se ...
- 《Cracking the Coding Interview》——第12章:测试——题目6
2014-04-25 00:53 题目:你要如何测试一个分布式银行系统的ATM机? 解法:ATM是Automatic Teller Machine,取钱的.我想了半天,没找到什么很清晰的思路,也许是因 ...
- 《Cracking the Coding Interview》——第12章:测试——题目5·
2014-04-25 00:41 题目:怎么测试一支笔?(Pen?您老说的是钢笔?) 解法:这种简约而不简单的题目,实在是面试官最喜欢,面试者最头疼的类型了.面试官可以只花三秒,以一种灰常高贵冷艳的语 ...
- 《Cracking the Coding Interview》——第12章:测试——题目4
2014-04-25 00:35 题目:没有专门的测试工具,你要如何对一个网页进行压力测试? 解法:拼手速,拼电脑数量呗.快捷键+复制粘贴网址,狂搞一番.话说回来,有脚本语言的情况下,直接写个脚本来模 ...
随机推荐
- 【Tool】JDK8 安装
JDK8 2019-07-26 14:05:21 by冲冲 1. 下载 通常前往官网 https://www.oracle.com/technetwork/java/javase/download ...
- gantt甘特图可拖拽、编辑(vue、react都可用 highcharts)
前言 Excel功能强大,应用广泛.随着web应用的兴起和完善,用户的要求也越来越高.很多Excel的功能都搬到了sass里面.恨不得给他们做个Excel出来...程序员太难了... 去年我遇到了 ...
- idea插件 Background Image Plus 随机更换背景图片
首先在市场搜索: Background Image Plus 设置图片: 在view中,有set 图片,有random图片,有clean图片的 设置就是用set,随便设置个路径. 重点来了,随机更换背 ...
- 使用微软RPA工具 Power Automate自动完成重复性工作
介绍 最近发现了win11自带了一个有趣的功能,可以自动去执行一些流程的工作.恰好目前每天早上都需要去提醒同事填写日计划,刚好可以试用下. 这是官网上对此功能的介绍 可以看到,对于win11我们是可以 ...
- PAML 选择压力的计算
简介 PAML(Phylogenetic Analysis by Maximum Likelihood)是伦敦大学的杨子恒(Yang Ziheng)教 授开发的一套基于最大似然估计来对蛋白质和核酸序列 ...
- Golang gRPC调试工具
目录 Golang gRPC调试工具 1. 命令行工具 grpcurl 1.1 安装 1.2 验证 1.3 注册反射 1.4 使用示例 2. web调试工具grpcui 2.1 安装 2.2 验证 2 ...
- linux 网络配置管理
[1]网络配置基础 (1)用户既可以通过命令行的方式,也可以通过友好的图形界面,轻松完成网络配置. (2)实现Linux网络配置的惟一目标就是修改系统中众多的网络配置文件, 如/etc/interfa ...
- cp -拷贝文件出现错误
对于cp -a最主要的用法是在保留原文件属性的前提下复制文件. 如果出现了拷贝文件错误,在文件前面加上-a 即可
- UE4 C++工程以Game模式启动
UE4版本:4.24.3源码编译版本 Windows10 + VS2019环境 UE4 C++工程,默认情况下VS中直接运行是启动Editor模式: 有时为了调试等目的需要以Game模式启动,可以避免 ...
- Angular中怎样创建service服务来实现组件之间调用公共方法
Angular组件之间不能互相调用方法,但是可以通过创建服务来实现公共方法的调用. 实现 创建服务命令 ng g service 服务路径/服务名 比如这里在app/services目录下创建stor ...