AcWing 4443.无限区域

原题链接:AcWing 4443.无限区域
题目来源:夏季每日一题2023

给定一个无限大的二维平面,设点 S 为该平面的中心点。

设经过点 S 的垂直方向的直线为 P,如果直线 P 是一个圆的切线,且切点恰好为点 S,那么:

如果该圆位于直线 P 的右侧,则称之为右圆。
如果该圆位于直线 P 的左侧,则称之为左圆。
现在,给定三个整数 R , A , B ,你需要按照右圆、左圆、右圆、左圆…的顺序不断画圆,具体要求如下:

  • 第一个右圆的半径等于 R
  • 每个左圆的半径等于你画的上一个圆的半径乘以 A
  • 每个右圆(第一个除外)的半径等于你画的上一个圆的半径除以 B(向下取整)。
  • 当你要画的圆的半径等于 0 时,绘画停止。

请你计算,所有画出的圆的面积之和。

保证绘画会在有限数量的步骤后停止。

输入格式
第一行包含整数 T ,表示共有 T 组测试数据。

每组数据占一行,包含三个整数 R , A , B

输出格式
每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: y ,其中 x 为组别编号(从 1 开始),y 为面积和(实数)。

y 在正确答案的 10−6 的绝对或相对误差范围内,则视为正确。

数据范围

  • 1≤T≤100,
  • 1≤R≤105,
  • 1≤A≤500,
  • 2×A≤B≤1000。

输入样例:

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为止
那么直接模拟就可以了

C++ 代码实现:

#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;
}

补充:

PI的写法:

arccos(-1)的结果就是π

#include 

const double PI = acos(-1); // 也可以定义3.1415926

你可能感兴趣的:(每日一题,算法)