CSP-S 2021 提高级 第一轮(初赛) 阅读程序(1)

【题目】

CSP-S 2021 提高级 第一轮(初赛) 阅读程序(1)

01 #include <iostream>
02 #include <cmath>
03 using namespace std;
04
05 const double r = acos(0.5);
06
07 int a1, b1, c1, d1;
08 int a2, b2, c2, d2;
09 
10 inline int sq(const int x) { return x * x; }
11 inline int cu(const int x) { return x * x * x; }
12 
13 int main()
14 {
15     cout.flags(ios::fixed);
16     cout.precision(4);
17
18     cin >> a1 >> b1 >> c1 >> d1;
19     cin >> a2 >> b2 >> c2 >> d2;
20
21     int t = sq(a1 - a2) + sq(b1 - b2) + sq(c1 - c2);
22
23     if (t <= sq(d2 - d1)) cout << cu(min(d1, d2)) * r * 4;
24     else if (t >= sq(d2 + d1)) cout << 0;
25     else {
26         double x = d1 - (sq(d1) - sq(d2) + t) / sqrt(t) / 2;
27         double y = d2 - (sq(d2) - sq(d1) + t) / sqrt(t) / 2;
28         cout << (x * x * (3 * d1 - x) + y * y * (3 * d2 - y)) * r;
29     }
30     cout << endl;
31     return 0;
32 }

假设输入的所有数的绝对值都不超过 1000,完成下面的判断题和单选题:
判断题

  1. 将第 21 行中 t 的类型声明从 int 改为 double,不会影响程序运行的结果。( )
  2. 将第 26、27 行中的“/ sqrt(t) / 2”替换为“/ 2 / sqrt(t)”,不会影响程序运行的结果。( )
  3. 将第 28 行中的“x * x”改成“sq(x)”、“y * y”改成“sq(y)” ,不会影响程序运行的结果。( )
  4. 当输入为“0 0 0 1 1 0 0 1”时,输出为“1.3090”。( )

单选题

  1. 当输入为“1 1 1 1 1 1 1 2”时,输出为( )。
    A. “3.1416”
    B. “6.2832”
    C. “4.7124”
    D. “4.1888”

  2. 这段代码的含义为( )。
    A. 求圆的面积并
    B. 求球的体积并
    C. 求球的体积交
    D. 求椭球的体积并

【题目考点】

1. 数学:求球的体积交

球的体积公式V=43πr3V=\frac{4}{3}\pi r^3V=34πr3rrr是球的半径。
求两球相交的体积
现有两球,第一个求半径为r1r_1r1,球心为C1C_1C1。第二个球半径为r2r_2r2,球心为C2C_2C2,两球球心之间的距离为ddd

  • 如果d≥r1+r2d\ge r_1+r_2dr1+r2,两球不相交,相交体积为0。
  • 如果d≤∣r2−r1∣d\le|r_2-r_1|dr2r1
    不失一般性,假设r1<r2r_1<r_2r1<r2,那么d≤r2−r1d\le r_2-r_1dr2r1,即r1+d≤r2r_1+d\le r_2r1+dr2,第一个球中距离第二个球球心C2C_2C2最远的点,到C2C_2C2的距离为r1+dr_1+dr1+d,由于r1+d≤r2r_1+d\le r_2r1+dr2,所以第一个球的所有点都在第二个球之中,即第一个球被第二个球包含,因此两球相交体积为第一个球的体积,即半径较小的球的体积。
    因此两球相交的体积为43πmin⁡{r1,r2}3\frac{4}{3}\pi \min\{r_1,r_2\}^334πmin{r1,r2}3
  • 如果∣r2−r1∣<d<r1+r2|r_2-r_1|<d<r_1+r_2r2r1<d<r1+r2,那么两球相交的部分为两个球缺
    在这里插入图片描述

球缺是指球体被平面截去一部分后剩余的部分。上图小圆面上方部分即为球缺。
垂直于截面的直径被此截面截得的线段长称为球缺的高,图中球缺的高为h。已知球半径r,以及球缺的高h,求球缺的体积。
可以将球缺横向切成很多个近似的小圆柱,每个圆柱的底面积是一个球的截面圆的面积,高为微分dxdxdx,进行积分。
在这里插入图片描述

设截面圆圆心B到球缺高与球面交点A的长度AB=xAB=xAB=x,那么BO=r−xBO=r-xBO=rx,截面圆半径BCBCBC的平方为r2−(r−x)2r^2-(r-x)^2r2(rx)2,截面圆面积为π(r2−(r−x)2)\pi(r^2-(r-x)^2)π(r2(rx)2),一个小圆柱的体积为π(r2−(r−x)2) dx\pi(r^2-(r-x)^2)\,dxπ(r2(rx)2)dxxxx最小为0,最大为球缺的高hhh,因此球缺的体积为:
∫0hπ(r2−(r−x)2) dx=∫0hπ(r2−r2−x2+2rx) dx=π∫0h(2rx−x2) dx=π(rx2∣0h−x33∣0h)=π(rh2−h33)=π3(3r−h)h2\int_0^h\pi(r^2-(r-x)^2)\,dx\\ =\int_0^h\pi(r^2-r^2-x^2+2rx)\,dx\\ =\pi \int_0^h(2rx-x^2)\,dx\\ =\pi(rx^2|_0^h-\frac{x^3}{3}|_0^h)\\ =\pi(rh^2-\frac{h^3}{3})\\ =\frac{\pi}{3}(3r-h)h^20hπ(r2(rx)2)dx=0hπ(r2r2x2+2rx)dx=π0h(2rxx2)dx=π(rx20h3x30h)=π(rh23h3)=3π(3rh)h2
因此半径为r,球缺高为h的球缺体积V′=π3(3r−h)h2V'=\dfrac{\pi}{3}(3r-h)h^2V=3π(3rh)h2

两球相交如图所示:
在这里插入图片描述

球心为C1C_1C1的球半径为r1r_1r1,球心为C2C_2C2的求半径为r2r_2r2
两球心之间的距离C1C2=dC_1C_2=dC1C2=d,红色线表示两球相交的截面,截面与球心连线垂直,ABABAB是截面中的一条线,因此有AB⊥C1C2AB\perp C_1C_2ABC1C2
BC2=xBC_2=xBC2=x,则BC1=d−xBC_1=d-xBC1=dx
根据勾股定理AC12−BC12=AB2=AC22−BC22AC_1^2-BC_1^2=AB^2=AC_2^2-BC_2^2AC12BC12=AB2=AC22BC22
所以r12−(d−x)2=r22−x2r_1^2-(d-x)^2=r_2^2-x^2r12(dx)2=r22x2
r12−d2−x2+2dx=r22−x2r_1^2-d^2-x^2+2dx=r_2^2-x^2r12d2x2+2dx=r22x2
2dx=r22−r12+d22dx=r_2^2-r_1^2+d^22dx=r22r12+d2
x=r22−r12+d22dx=\dfrac{r_2^2-r_1^2+d^2}{2d}x=2dr22r12+d2
两球相交部分中,以C2C_2C2为球心的球的球缺的高为:
h2=BP2=C2P2−C2B=r2−x=r2−r22−r12+d22dh_2=BP_2=C_2P_2-C_2B=r_2-x=r_2-\dfrac{r_2^2-r_1^2+d^2}{2d}h2=BP2=C2P2C2B=r2x=r22dr22r12+d2
C1C_1C1为球心的球的球缺的高为:
h1=BP1=C1P1−C1B=r1−(d−x)=r1−(d−r22−r12+d22d)=r1−2d2−r22+r12−d22d=r1−r12−r22+d22dh_1=BP_1=C_1P_1-C_1B=r_1-(d-x)\\ =r_1-(d-\dfrac{r_2^2-r_1^2+d^2}{2d})\\ =r_1-\dfrac{2d^2-r_2^2+r_1^2-d^2}{2d}\\ =r_1-\dfrac{r_1^2-r_2^2+d^2}{2d}h1=BP1=C1P1C1B=r1(dx)=r1(d2dr22r12+d2)=r12d2d2r22+r12d2=r12dr12r22+d2
总结:两球相交部分为两个球缺
第一个球的球缺半径为r1r_1r1,高为h1=r1−r12−r22+d22dh_1=r_1-\dfrac{r_1^2-r_2^2+d^2}{2d}h1=r12dr12r22+d2,体积为π3(3r1−h1)h12\dfrac{\pi}{3}(3r_1-h_1)h_1^23π(3r1h1)h12
第二个球的球缺半径为r2r_2r2,高为h2=r2−r22−r12+d22dh_2=r_2-\dfrac{r_2^2-r_1^2+d^2}{2d}h2=r22dr22r12+d2,体积为π3(3r2−h2)h22\dfrac{\pi}{3}(3r_2-h_2)h_2^23π(3r2h2)h22
球相交部分体积为:π3((3r1−h1)h12+(3r2−h2)h22)\dfrac{\pi}{3}((3r_1-h_1)h_1^2+(3r_2-h_2)h_2^2)3π((3r1h1)h12+(3r2h2)h22)

2. 数学:反三角函数

【解题思路】

10 inline int sq(const int x) { return x * x; }
11 inline int cu(const int x) { return x * x * x; }

函数sq(x)求x的平方,cu(x)求x的立方。inline表示该函数是内联函数,在编译后不进行真正的函数调用,可以加快运行速度。

15     cout.flags(ios::fixed);
16     cout.precision(4);

这两句是作用是以下进行输出浮点型量时,会保留四位小数输出。

18     cin >> a1 >> b1 >> c1 >> d1;
19     cin >> a2 >> b2 >> c2 >> d2;
20
21     int t = sq(a1 - a2) + sq(b1 - b2) + sq(c1 - c2);

输入a1,b1,c1,d1,a2,b2,c2,d2a_1,b_1,c_1,d_1,a_2,b_2,c_2,d_2a1,b1,c1,d1,a2,b2,c2,d2 8个变量,看变量名大概可以推测:a1,b1,c1,d1a_1,b_1,c_1,d_1a1,b1,c1,d1是相关的四个量,a2,b2,c2,d2a_2,b_2,c_2,d_2a2,b2,c2,d2是相关的四个量。
t的值为t=(a1−a2)2+(b1−b2)2+(c1−c2)2t=(a_1-a_2)^2+(b_1-b_2)^2+(c_1-c_2)^2t=(a1a2)2+(b1b2)2+(c1c2)2

05 const double r = acos(0.5);

已知弧度与角度的转化关系:π 弧度=180角度\pi\ 弧度 = 180角度π 弧度=180角度
设有直角三角形,∠A=60°=π3\angle A=60\degree= \frac{\pi}{3}A=60°=3π∠B=30°=π6\angle B=30\degree=\frac{\pi}{6}B=30°=6π∠C=90°=π2\angle C=90\degree=\frac{\pi}{2}C=90°=2π,那么∠A\angle AA的余弦值,即∠A\angle AA邻边比斜边的比值为cosπ3=12cos\frac{\pi}{3}=\frac{1}{2}cos3π=21arccos⁡\arccosarccoscoscoscos的反三角函数,所以arccos12=π3arccos \frac{1}{2} = \frac{\pi}{3}arccos21=3π

代码中r的值为r=arccos12=π3r=arccos \frac{1}{2} = \dfrac{\pi}{3}r=arccos21=3π

23     if (t <= sq(d2 - d1)) cout << cu(min(d1, d2)) * r * 4;
24     else if (t >= sq(d2 + d1)) cout << 0;

t≤(d2−d1)2t\le (d_2-d_1)^2t(d2d1)2时,输出4r(min⁡{d1,d2})3=43π(min⁡{d1,d2})34r(\min\{d_1,d_2\})^3=\frac{4}{3}\pi(\min\{d_1,d_2\})^34r(min{d1,d2})3=34π(min{d1,d2})3
看这个公式的形式,符合球的体积公式,因此min⁡{d1,d2}\min\{d_1,d_2\}min{d1,d2}应该是球的半径,这是输出了半径为min⁡{d1,d2}\min\{d_1,d_2\}min{d1,d2}的球的体积。

t≥(d2+d1)2t\ge (d_2+d_1)^2t(d2+d1)2时,输出0。
结合ttt的定义,看到这里时,基本可以确定(a1,b1,c1)(a_1,b_1,c_1)(a1,b1,c1)是第1个球的球心,半径为d1d_1d1(a2,b2,c2)(a_2,b_2,c_2)(a2,b2,c2)为第2个球的球心,半径为d2d_2d2
两个球心的距离为(a1−a2)2+(b1−b2)2+(c1−c2)2=t\sqrt{(a_1-a_2)^2+(b_1-b_2)^2+(c_1-c_2)^2} = \sqrt{t}(a1a2)2+(b1b2)2+(c1c2)2=t,因此ttt是两球心距离的平方。

  • 当球心距离t≤∣d2−d1∣\sqrt{t}\le |d_2-d_1|td2d1时,半径为max⁡{d1,d2}\max\{d_1,d_2\}max{d1,d2}的球包含半径为min⁡{d1,d2}\min\{d_1,d_2\}min{d1,d2}的球,两球交(重合)的部分的体积为较小球的体积43π(min⁡{d1,d2})3\frac{4}{3}\pi(\min\{d_1,d_2\})^334π(min{d1,d2})3
  • 当球心距离t≥∣d2+d1∣\sqrt{t}\ge |d_2+d_1|td2+d1时,两球不相交,相交体积为0。
  • 当球心距离∣d2−d1∣<t<∣d2+d1∣|d_2-d_1|<\sqrt{t}<|d_2+d_1|d2d1<t<d2+d1时,就要球两球相交的体积。
26         double x = d1 - (sq(d1) - sq(d2) + t) / sqrt(t) / 2;
27         double y = d2 - (sq(d2) - sq(d1) + t) / sqrt(t) / 2;
28         cout << (x * x * (3 * d1 - x) + y * y * (3 * d2 - y)) * r;

相信高中不会教这个知识点,我们做这个题也不需要真的了解求两球相交体积的方法,只要看出该题求的是球相交的体积,就可以把下面的题做对。
具体的求球相交体积的原理见上文【题目考点】。
h1=r1−r12−r22+d22dh_1=r_1-\dfrac{r_1^2-r_2^2+d^2}{2d}h1=r12dr12r22+d2h2=r2−r22−r12+d22dh_2=r_2-\dfrac{r_2^2-r_1^2+d^2}{2d}h2=r22dr22r12+d2
球相交的体积为π3((3r1−h1)h12+(3r2−h2)h22)\dfrac{\pi}{3}((3r_1-h_1)h_1^2+(3r_2-h_2)h_2^2)3π((3r1h1)h12+(3r2h2)h22)
本题d1d_1d1为公式中的r1r_1r1,本题d2d_2d2为公式中的r2r_2r2,本题t\sqrt{t}t为公式中的ddd。本题xxx为公式中的h1h_1h1,本题yyy为公式中的h2h_2h2。本题rrrπ3\dfrac{\pi}{3}3π
题目中的代码就是在实现上述公式,可以求出两球相交的体积。

判断题
1. 将第 21 行中 t 的类型声明从 int 改为 double,不会影响程序运行的结果。( )
答:T
将t设为double类型后,下面代码中t参与的表达式的计算过程从整数计算变为了实数计算,虽说进行实数计算有可能产生偏差,不过绝大部分情况下不会出现精度问题,可以认为不会影响程序结果。

2. 将第 26、27 行中的“/ sqrt(t) / 2”替换为“/ 2 / sqrt(t)”,不会影响程序运行的结果。( )
答:F

26         double x = d1 - (sq(d1) - sq(d2) + t) / sqrt(t) / 2;
27         double y = d2 - (sq(d2) - sq(d1) + t) / sqrt(t) / 2;

表达式(sq(d1) - sq(d2) + t)的值是int类型的,sqrt(t)的值是double类型的,二者相除会进行实数除法,再除以2也是进行实数除法,会得到小数结果。
如果改为

26         double x = d1 - (sq(d1) - sq(d2) + t) / 2 / sqrt(t);
27         double y = d2 - (sq(d2) - sq(d1) + t) / 2 / sqrt(t);

表达式(sq(d1) - sq(d2) + t)的值是int类型的,2也是int类型的,二者相除会进行整数除法运算,正整数进行整数除法,商为实数除法的商向下取整(如5/2表达式的值为2)。因此这一步进行实数除法可能会产生精度丢失,表达式的值与预期进行实数除法的结果不同。再进行后续计算,结果也是错误的。
因此修改后会影响程序运行的结果。

3. 将第 28 行中的“x * x”改成“sq(x)”、“y * y”改成“sq(y)” ,不会影响程序运行的结果。( )
答:F
由于sq函数的定义为

10 inline int sq(const int x) { return x * x; }

参数类型为int,而第28行使用的x、y为double类型的变量,将double类型量传给int类型的参数,会发生double到int的类型转化,可能会丢失精度。而第28行求的是实数x或y的平方,不能使用求整数平方的sq函数。

例:x的值为1.5,传入sq函数后,sq函数内参数x的值为1,sq(x)返回1。而x*x表达式的值为2.25。

4. 当输入为“0 0 0 1 1 0 0 1”时,输出为“1.3090”。( )
答:T
第一个球的球心为(0,0,0)(0,0,0)(0,0,0),半径为1。第二个球的球心为(1,0,0)(1, 0, 0)(1,0,0),半径为1。两求的交
求出t=(a1−a2)2+(b1−b2)2+(c1−c2)2=1t=(a_1-a_2)^2+(b_1-b_2)^2+(c_1-c_2)^2=1t=(a1a2)2+(b1b2)2+(c1c2)2=1
根据这段代码的逻辑进行手算:

26         double x = d1 - (sq(d1) - sq(d2) + t) / sqrt(t) / 2;
27         double y = d2 - (sq(d2) - sq(d1) + t) / sqrt(t) / 2;
28         cout << (x * x * (3 * d1 - x) + y * y * (3 * d2 - y)) * r;

x=d1−(d12−d22+t)/t/2=1−(1−1+1)/1/2=0.5x=d_1-(d_1^2-d_2^2+t)/\sqrt{t}/2=1-(1-1+1)/1/2=0.5x=d1(d12d22+t)/t/2=1(11+1)/1/2=0.5
y=d2−(d22−d12+t)/t/2=1−(1−1+1)/1/2=0.5y=d_2-(d_2^2-d_1^2+t)/\sqrt{t}/2=1-(1-1+1)/1/2=0.5y=d2(d22d12+t)/t/2=1(11+1)/1/2=0.5
输出值(x2(3d1−x)+y2(3d2−y))r=14(3∗1−0.5+3∗1−0.5)∗π3=5π12(x^2(3d_1-x)+y^2(3d_2-y))r\\=\frac{1}{4}(3*1-0.5+3*1-0.5)*\frac{\pi}{3}\\ =\frac{5\pi}{12}(x2(3d1x)+y2(3d2y))r=41(310.5+310.5)3π=125π
由于最终结果要求保留到小数点后4位,因此π\piπ取到小数点后5位进行计算。
5π12≈5∗3.1415912=1.308995≈1.3090\frac{5\pi}{12}\approx\frac{5*3.14159}{12}=1.308995\approx 1.3090125π1253.14159=1.3089951.3090
该叙述正确。

单选题

5. 当输入为“1 1 1 1 1 1 1 2”时,输出为( )。
A. “3.1416”
B. “6.2832”
C. “4.7124”
D. “4.1888”

答:D
第一个球的球心为(1,1,1)(1,1,1)(1,1,1),半径为1。第二个球的球心为(1,1,1)(1,1,1)(1,1,1),半径为2。显然第二个球包含第一个球,两个求的相交部分为第一个球的体积,为
V=43πr3=43πV=\frac{4}{3}\pi r^3=\frac{4}{3}\piV=34πr3=34π
由于最终结果要求保留到小数点后4位,因此π\piπ取到小数点后5位进行计算。
43π≈4∗3.141593=4.18878≈4.1888\frac{4}{3}\pi\approx\frac{4*3.14159}{3}=4.18878\approx 4.188834π343.14159=4.188784.1888,因此选D。

6. 这段代码的含义为( )。
A. 求圆的面积并
B. 求球的体积并
C. 求球的体积交
D. 求椭球的体积并

答:C
本题求的是两球相交部分的体积,选C。

【答案】

  1. T
  2. F
  3. F
  4. T
  5. D
  6. C
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值