题目链接
题目描述
在平面直角坐标系中,给定一个位于第一象限的点 。你需要构造一个圆,满足以下两个条件:
- 圆和 x 轴、y 轴都相切。
- 圆经过点
。
题目保证存在两个这样的圆。你需要从小到大输出这两个圆的半径。
解题思路
这是一个典型的解析几何问题。我们可以通过将几何约束转化为代数方程来求解。
1. 建立坐标系与方程
- 几何约束:一个在第一象限内且同时与 x 轴和 y 轴相切的圆,其圆心坐标必定为
,其中
是圆的半径。
- 圆的标准方程:根据圆心和半径,我们可以写出该圆的方程:
2. 代入已知点
- 代数约束:题目要求圆必须经过点
。这意味着该点的坐标必须满足圆的方程。我们将
和
代入方程中:
3. 求解关于半径
的二次方程
我们得到了一个关于半径 的一元二次方程。接下来,我们展开并整理它:
- 展开平方项:
- 合并同类项,整理成标准二次方程
的形式:
4. 使用求根公式
现在我们可以使用二次方程的求根公式 来解出
。
计算判别式(根号下的部分) :
将 代入求根公式:
5. 最终答案
这样我们就得到了两个半径的解:
由于 总是正的,所以
。我们按顺序输出这两个值即可。
代码
#include <iostream>
#include <cmath>
#include <iomanip>
#include <algorithm>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
double px, py;
cin >> px >> py;
double term = sqrt(2.0 * px * py);
double sum = px + py;
double r1 = sum - term;
double r2 = sum + term;
// Although the derivation guarantees r1 < r2, using min/max is safer
// in case of floating point inaccuracies with very specific inputs.
cout << fixed << setprecision(6) << min(r1, r2) << " " << max(r1, r2) << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double px = sc.nextDouble();
double py = sc.nextDouble();
double term = Math.sqrt(2.0 * px * py);
double sum = px + py;
double r1 = sum - term;
double r2 = sum + term;
// Outputting in sorted order
if (r1 > r2) {
double temp = r1;
r1 = r2;
r2 = temp;
}
System.out.printf("%.6f %.6f\n", r1, r2);
}
}
import math
def solve():
try:
px, py = map(float, input().split())
except (IOError, ValueError):
return
term = math.sqrt(2.0 * px * py)
sum_val = px + py
r1 = sum_val - term
r2 = sum_val + term
# Ensure sorted output
if r1 > r2:
r1, r2 = r2, r1
print(f"{r1:.6f} {r2:.6f}")
solve()
算法及复杂度
-
算法:解析几何、数学推导
-
时间复杂度:
。
- 整个计算过程只涉及几次基本的算术运算(加法、乘法、开方),其时间与输入值的大小无关。
-
空间复杂度:
。
- 只需要常数个变量来存储输入和计算结果。