小红的圆构造
[题目链接](https://www.nowcoder.com/practice/3309f6e285f04c74a8ee4804210224ca)
思路
给定一个坐标为 的点(
),要构造一个同时与两条坐标轴相切且经过该点的圆,输出两个解的半径(升序)。
圆的性质
与两条坐标轴都相切的圆,其圆心到 轴和
轴的距离都等于半径
。因此圆心坐标为
。
由于点 在第一象限(
),只有圆心在
的情况才能使圆经过该点(其他象限的圆心会导致距离过大或无解)。
列方程
圆心 ,半径
,经过点
:
$$
(x - r)^2 + (y - r)^2 = r^2
$$
展开:
$$
x^2 - 2xr + r^2 + y^2 - 2yr + r^2 = r^2
$$
化简得到关于 的一元二次方程:
$$
r^2 - 2(x + y)r + (x^2 + y^2) = 0
$$
求解
由求根公式:
$$
r = \frac{2(x+y) \pm \sqrt{4(x+y)^2 - 4(x^2+y^2)}}{2} = (x+y) \pm \sqrt{2xy}
$$
判别式 (因为
),所以恰好有两个正实数解。
较小的半径为 ,较大的为
,直接输出即可。
样例验证
输入 :
,即
,
,与样例一致。
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
double x, y;
scanf("%lf%lf", &x, &y);
double s = x + y;
double d = sqrt(2.0 * x * y);
printf("%.8f %.8f\n", s - d, s + d);
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double x = sc.nextDouble(), y = sc.nextDouble();
double s = x + y;
double d = Math.sqrt(2.0 * x * y);
System.out.printf("%.8f %.8f%n", s - d, s + d);
}
}
import math
x, y = map(int, input().split())
s = x + y
d = math.sqrt(2 * x * y)
print(f"{s - d:.8f} {s + d:.8f}")
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
rl.on('line', (line) => {
const [x, y] = line.trim().split(/\s+/).map(Number);
const s = x + y;
const d = Math.sqrt(2 * x * y);
console.log((s - d).toFixed(8) + ' ' + (s + d).toFixed(8));
rl.close();
});
复杂度分析
- 时间复杂度:
,只需一次加法和一次开方运算。
- 空间复杂度:
,只使用常数个变量。

京公网安备 11010502036488号