原题链接:AcWing 4443.无限区域
题目来源:夏季每日一题2023
给定一个无限大的二维平面,设点 S
为该平面的中心点。
设经过点 S
的垂直方向的直线为 P
,如果直线 P
是一个圆的切线,且切点恰好为点 S
,那么:
如果该圆位于直线 P
的右侧,则称之为右圆。
如果该圆位于直线 P
的左侧,则称之为左圆。
现在,给定三个整数 R
, A
, B
,你需要按照右圆、左圆、右圆、左圆…的顺序不断画圆,具体要求如下:
R
。A
。B
(向下取整)。请你计算,所有画出的圆的面积之和。
保证绘画会在有限数量的步骤后停止。
输入格式
第一行包含整数 T
,表示共有 T
组测试数据。
每组数据占一行,包含三个整数 R
, A
, B
。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为 Case #x: y
,其中 x
为组别编号(从 1 开始),y
为面积和(实数)。
y 在正确答案的 10−6 的绝对或相对误差范围内,则视为正确。
数据范围
输入样例:
2
1 3 6
5 2 5
输出样例:
Case #1: 31.415927
Case #2: 455.530935
样例解释
对于 case #1:
首先画一个半径为 1 的右圆
然后画一个半径为 1×3=3 的左圆
随后停止绘画
因为下一个右圆的半径为 ⌊3/6⌋=0。
对于 case #2:
第一步画一个半径为 5 的右圆;
第二步画一个半径为 5×2=10 的左圆;
第三步画一个半径为 ⌊10/5⌋=2 的右圆;
第四步画一个半径为 2×2=4 的左圆;
停止绘画,因为下一个右圆的半径为 ⌊4/5⌋=0。
别管左圆右圆,题目要求就是求一系列圆的面积,半径开始为r,下一个圆的半径再上一个圆半径基础上乘a,再下一个圆再在上一个圆基础上除以b并下取整……重复以上过程,知道圆的半径为0为止
那么直接模拟就可以了
#include
#include
using namespace std;
const double PI = acos(-1); // 也可以定义3.1415926
int t, r, a, b;
// 计算面积
double area(double r){
return r * r * PI;
}
int main(){
scanf("%d", &t);
for(int cases = 1; cases <= t; cases ++ ){
scanf("%d%d%d", &r, &a, &b);
double res = area(r);
while(r){
r *= a;
res += area(r);
r /= b; // 题目要求下取整
res += area(r);
}
printf("Case #%d: %.6lf\n", cases, res);
}
return 0;
}
arccos(-1)的结果就是π
#include
const double PI = acos(-1); // 也可以定义3.1415926