工程建设网站导航图,更换dns能上国外网站吗,小程序api手册,怎么制作网站文章目录4.1 函数的概念与使用本节习题前面我们说到#xff0c;机器人服务员可能需要反复不断地执行 “检测杯子是否干净” 的动作#xff0c;这个操作是具有封闭性的。具体来说#xff0c;这个操作会以一个杯子作为操作对象#xff0c;以是否干净作为检测结果#xff0c;…文章目录4.1 函数的概念与使用本节习题前面我们说到机器人服务员可能需要反复不断地执行 “检测杯子是否干净” 的动作这个操作是具有封闭性的。具体来说这个操作会以一个杯子作为操作对象以是否干净作为检测结果我们只需要给这个操作传递一个杯子然后获取操作结果即可我们不需要知道它的检测流程和步骤就像一个黑盒工具。4.1 函数的概念与使用在程序中我们可以把这种具有特定功能的代码块封装成一个黑盒称为函数在需要使用时直接调用即可。这样的程序设计模式称为模块化程序设计是一种能够让程序逻辑清晰、易于维护的设计模式。在学习如何封装函数之前我们先来学习一些 C 标准中已经封装好的工具函数。【P2173 [ABC070B] 两个开关】Alice 和 Bob 都有一个开关用来控制机器人。Alice 在a aa秒按下开关移动机器人并在b bb秒释放开关。Bob 在c cc秒按下开关移动机器人并在d dd秒释放开关。求 Alice 和 Bob 都按下开关的秒数。两人都按下开关的时间应该从较晚按下开关的时刻开始到较早释放开关的时刻结束即从a aa和c cc的较大值开始到b bb和d dd的较小值结束。可以使用max()函数求出两个数的较大值使用min()函数求出两个数的较小值然后用两个函数的返回结果相减即可用法格式见示例代码。需要注意的是有可能出现一个人已经释放开关第二个人还没有按下开关的情况也就是说上述相减得到的结果有可能为负数此时应当将答案修正为0 00换句话说答案应该是上述相减的结果与0 00相比得到的较大值。intsmax(a,c);// 计算两人都按下开关的开始时刻inttmin(b,d);// 计算两人都按下开关的结束时刻coutmax(t-s,0);// 计算两人都按下开关的秒数函数max()和min()需要接收两个相同类型的数据作为操作对象称为参数上述代码中a aa和c cc就是传递给max()函数的参数。第三行代码告诉我们参数既可以是变量也可以是常量只要数据类型相同即可。这两个函数会把比较结果以返回值的形式呈现出来返回值的类型与参数类型一致。事实上我们可以把max(a, c)看作 “函数表达式”该表达式的值类型与参数类型一致于是既可以把返回值存储在变量中也可以直接输出。除此之外函数返回值还可以参与更进一步的运算看下面的例子。【P2151 [CF581A] Vasya the Hipster】嬉皮士 Vasya 有a aa只红袜子和b bb只蓝袜子不区分左右。根据最新的流行趋势潮人应该穿不同颜色的袜子左脚穿红色袜子右脚穿蓝色袜子。每天早上Vasya 穿上新袜子在睡觉前把它们扔掉因为她不想洗它们。Vasya 想知道她能穿不同颜色的袜子的最长天数是多少天。在那之后的几天里她将穿同样颜色的袜子直到她的袜子用完或者不能用她的袜子做一双。输出 Vasya 可以穿不同颜色的袜子的最长天数和她可以穿同样颜色的袜子的天数。可以穿不同颜色的袜子的最长天数应该是min ⁡ ( a , b ) \min(a, b)min(a,b)剩下的相同颜色袜子数量为t max ⁡ ( a , b ) − min ⁡ ( a , b ) t \max(a, b) - \min(a, b)tmax(a,b)−min(a,b)于是穿同样颜色的袜子的天数为⌊ t / 2 ⌋ \lfloor t/2\rfloor⌊t/2⌋。甚至我们可以直接省略变量t tt写出如下代码。coutmin(a,b) (max(a,b)-min(a,b))/2;事实上max ⁡ ( a , b ) − min ⁡ ( a , b ) \max(a, b) - \min(a, b)max(a,b)−min(a,b)就是a − b a-ba−b的绝对值可以使用cmath或math.h头文件中的数学函数abs()求出一个数的绝对值用法如下。coutmin(a,b) abs(a-b)/2;函数abs()除了用于求绝对值之外最常用到的地方是浮点数比较。浮点数在计算机中并不能保证精确存储往往存在一个较小的误差例如0.1 0.10.1可能存储为0.099999... 0.099999...0.099999...或者0.1000..1 0.1000..10.1000..1。因此在比较浮点数是否相等时建议不要直接使用进行比较而是根据题目所要求的精度设置一个误差限来进行比较以此避免浮点数的不精确存储导致的比较错误一般可以设置为10 − 6 10^{-6}10−6或者10 − 9 10^{-9}10−9具体参考下面的代码。constdoubleeps1e-6;if(abs(s1-s2)eps){// 认为 s1 和 s2 相等}【G1112 [GESP2406 二级] 平方之和】小杨有n nn个正整数a 1 , a 2 , ⋯ , a n a_1,a_2,⋯,a_na1​,a2​,⋯,an​他想知道对于所有的i ( 1 ≤ i ≤ n ) i\ (1≤i≤n)i(1≤i≤n)是否存在两个正整数x xx和y yy满足x 2 y 2 a i x^2y^2a_ix2y2ai​1 ≤ a i ≤ 10 6 1\le a_i\le 10^61≤ai​≤106。不难想到可以用两层循环分别枚举x , y x,yx,y进行求解需要注意的是如果直接在[ 1 , a i ) [1, a_i)[1,ai​)范围内枚举x , y x,yx,y最坏情况下单个a i a_iai​就需要10 12 10^{12}1012次枚举验证。在学习for语句时曾提到算法竞赛中的每道题目都会有一个时间限制因此我们不仅要考虑算法的正确性还要考虑在给定时限内的可行性。一般而言算法竞赛中的绝大部分题目给出的时间限制是1 11秒基于现在主流的评测机配置1 11秒大约允许程序执行10 8 10^8108次算术运算、逻辑运算等基本操作。也就是说上述枚举算法在这个问题中会超时。分析给定的表达式x 2 y 2 a i x^2y^2 a_ix2y2ai​不难发现max ⁡ ( x , y ) a i \max(x, y) \sqrt{a_i}max(x,y)ai​​于是我们只需要在[ 1 , a i ) [1, \sqrt{a_i})[1,ai​​)范围内枚举x , y x,yx,y即可使用cmath或math.h头文件中的数学函数sqrt()可以求出一个数的平方根。此外当找到符合要求的x , y x,yx,y之后即可提前结束枚举过程再次加快程序效率可以用标记法实现关键代码如下。boolflag0;// 假设不存在满足条件的 x 和 yfor(intx1;xsqrt(ai)!flag;x){for(inty1;ysqrt(ai)!flag;y){if(x*xy*yai){flag1;}}}if(flag)coutYes\n;elsecoutNo\n;需要注意的是函数sqrt()的返回值类型为double因为并不是所有数的平方根都为整数。在算法竞赛中为了避免调用函数sqrt()带来的额外开销一般会采用x * x ai来替代x sqrt(ai)。然而随着计算机硬件的发展调用函数的额外花销基本可以忽略不计因此上述替换并不是必需的。在学习嵌套循环枚举时我们分析过 [GSEP2303 二级] 百鸡问题这道题曾提到过利用等式的特性直接求出最后一个枚举量从而减少循环层数的方法。把这种方法应用在这个问题上可以将两层循环减少为一层循环进一步加快程序效率。假设我们枚举的量是x xx那么s a i − x 2 y 2 s a_i - x^2 y^2sai​−x2y2根据题目要求满足条件的y yy是正整数也就是说我们需要验证s ss是否为平方数。验证的思路是利用浮点数转换为整数的截断特性截取s \sqrt{s}s​的整数部分t tt如果t 0 t0t0并且t 2 s t^2st2s则说明s ss是平方数。由于在枚举时限制了x a i x \sqrt{a_i}xai​​因此在x xx和a i a_iai​都是整数的情况下必定有a i − x 2 ≥ 1 a_i-x^2 \ge 1ai​−x2≥1于是此处t 0 t0t0一定成立不必验证。boolflag0;for(intx1;xsqrt(ai)!flag;x){inttsqrt(ai-x*x);if(t*tai-x*x){flag1;}}if(flag)coutYes\n;elsecoutNo\n;【G1110 [GESP2406 一级] 立方数】小杨有一个正整数n nn他想知道n nn是否是一个立方数。一个正整数n nn是立方数当且仅当存在一个正整数x xx满足x × x × x n x×x×xnx×x×xn。与上述验证平方数的思路一致利用数学函数cbrt()求出n nn的立方根并截取其整数部分t tt如果t 3 n t^3 nt3n则说明n nn是立方数。函数cbrt同样声明在头文件cmath和math.h中。【D1310 [PAT 乙级] B 是 A 的多少倍】设一个数A AA的最低D DD位形成的数是a d adad。如果把a d adad截下来移到A AA的最高位前面就形成了一个新的数B BB。问B BB是A AA的多少倍保留2 22位小数。例如将12345 1234512345的最低2 22位45 4545截下来放到123 123123的前面就得到45123 4512345123它约是12345 1234512345的3.66 3.663.66倍。首先需要通过数位分离计算出A AA的位数n nn然后计算第D DD位从0 00开始下同的位权p pp方便取出低D DD位和高n − D n-Dn−D位。为了便于计算数字B BB可以求出第n − D n-Dn−D位的位权q qq由此可以计算出B ( A m o d p ) × q ⌊ A / p ⌋ B(A\mod p)\times q \lfloor A/p\rfloorB(Amodp)×q⌊A/p⌋。然后计算B / A B/AB/A即可注意在 C 中应使用表达式1.0 * B / A进行计算。计算p pp和q qq可以使用pow()函数pow(a, b)的作用是计算a b a^bab于是p pow(10, D)q pow(10, n-D)。函数pow()同样声明在头文件cmath和math.h中注意该函数的返回值为double类型不支持取余%运算因此为了保证取余运算的合法性应该把p pp和q qq声明为整型。intppow(10,D),qpow(10,n-D);intBA%p*qA/p;【P4936 [ABC215B] log2(N)】求出满足2 k ≤ n 2^k≤n2k≤n的最大非负整数k kk。请注意1 ≤ n ≤ 10 18 1≤n≤10^{18}1≤n≤1018。根据数学中对数的知识可以快速写出k ⌊ log ⁡ 2 n ⌋ k\lfloor \log_2 n\rfloork⌊log2​n⌋其中log ⁡ 2 n \log_2 nlog2​n读作 “以2 22为底n nn的对数”。C 中提供了计算对数的一系列函数 ——log()表示以e ee约等于2.71828 2.718282.71828为底log2()表示以2 22为底log10()表示以10 1010为底。以上这些函数都声明在头文件cmath和math.h中返回值均为double类型。本节习题P1566 [CF796A] Buying A HouseP1984 [CF620A] Professor GukiZ’s RobotP2160 [CF57A] Square Earth?P2871 [ABC256A] 2^NP2802 [ABC239A] HorizonG1160 [GESP2412 二级] 寻找数字