{ }codelper
乘方平方根溢出P0129

洒水器能浇到的花盆

花园里有一个洒水器和 n 个花盆。
第一行给出洒水器的位置 x0, y0 和水能到达的半径 r。
第二行给出花盆数 n,接下来 n 行每行给出一个花盆的位置 x, y。
如果洒水器与花盆之间的(直线)距离不超过 r,这个花盆就能浇到水。
第一行输出能浇到水的花盆数。
第二行输出不小于 r 的整数中、用作半径时能让所有花盆都浇到水的最小的一个(半径不会缩小)。
所以如果所有花盆已经都能浇到水,就原样输出 r。

输入
所有坐标都是 -100000 到 100000 的整数,0 ≤ r ≤ 300000,1 ≤ n ≤ 1000
输出
两行:浇到水的花盆数、不小于 r 的所需最小整数半径
样例 1 · stdin
0 0 5
4
3 4
6 0
-1 -1
0 -7
stdout
2
7
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

距离是 √(dx² + dy²),但保持平方来比较 dx² + dy² <= r²,只用整数就很精确。
陷阱在平方的大小。
坐标差最大 20 万,距离的平方可达 8×10^10,超过 32 位 int(约 21 亿)。
Java、C# 要用 long,C、C++ 要用 long long;用 int 会悄悄溢出,得到奇怪的值。
Python 的整数没有大小限制,JS、TS、Craykon 的数在 2^53 以内都是精确整数,所以这个范围没有问题。
幂运算是 Python/JS/TS **,Java/C# Math.pow/Math.Pow,C pow,C++ std::pow,后四个返回浮点数(double)。
Craykon 没有幂运算符,写成 dx * dx。
求平方用 dx * dx 最简单也最精确。
在 C、C++、Java、C#、JS、TS、Python 中 dx ^ 2 不是幂而是按位异或,不报错却给出错误的值。
第二行是对最远距离的平方 D 求 √D 再向上取整。
Python 用 math.isqrt 直接得到整数平方根;其他语言的稳妥习惯是先用 sqrt 估计,再把 s * s 和 D 比较修正后向上取整(在这个范围 double 平方根是对的,但更大的数可能差一)。
平方根:Python math.sqrt,JS/TS Math.sqrt,Java Math.sqrt,C# Math.Sqrt,C sqrt(<math.h>),C++ std::sqrt,Craykon 数学.平方根。
直接使用向下取整的平方根而不向上取整,半径会少 1。

Pythonmain.py · 17 行
import math x0, y0, r = map(int, input().split())n = int(input())watered = 0far = 0  # 가장 먼 화분까지 거리의 제곱for _ in range(n):    x, y = map(int, input().split())    d2 = (x - x0) ** 2 + (y - y0) ** 2  # 제곱끼리 비교하면 정수만으로 정확하다    if d2 <= r ** 2:        watered += 1    far = max(far, d2)s = math.isqrt(far)  # 정수 제곱근(내림)if s * s < far:    s += 1  # 올림print(watered)print(max(r, s))
JavaScriptmain.js · 13 行
const [x0, y0, r, n, ...pts] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);let watered = 0;let far = 0; // 가장 먼 화분까지 거리의 제곱for (let i = 0; i < n; i++) {  const d2 = (pts[2 * i] - x0) ** 2 + (pts[2 * i + 1] - y0) ** 2; // 8×10^10 이하라 number로 정확하다  if (d2 <= r ** 2) watered++;  far = Math.max(far, d2);}let s = Math.floor(Math.sqrt(far));while (s * s > far) s--; // 실수 제곱근이 한 칸 어긋나도 바로잡는다while ((s + 1) * (s + 1) <= far) s++;if (s * s < far) s++; // 올림console.log(watered + "\n" + Math.max(r, s));
TypeScriptmain.ts · 14 行
import { readFileSync } from "node:fs";const [x0, y0, r, n, ...pts]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);let watered = 0;let far = 0; // 가장 먼 화분까지 거리의 제곱for (let i = 0; i < n; i++) {  const d2: number = (pts[2 * i] - x0) ** 2 + (pts[2 * i + 1] - y0) ** 2; // 8×10^10 이하라 number로 정확하다  if (d2 <= r ** 2) watered++;  far = Math.max(far, d2);}let s: number = Math.floor(Math.sqrt(far));while (s * s > far) s--; // 실수 제곱근이 한 칸 어긋나도 바로잡는다while ((s + 1) * (s + 1) <= far) s++;if (s * s < far) s++; // 올림console.log(watered + "\n" + Math.max(r, s));
JavaMain.java · 23 行
import java.util.Scanner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        long x0 = sc.nextLong(), y0 = sc.nextLong(), r = sc.nextLong();        int n = sc.nextInt();        int watered = 0;        long far = 0; // 가장 먼 화분까지 거리의 제곱        for (int i = 0; i < n; i++) {            long dx = sc.nextLong() - x0, dy = sc.nextLong() - y0;            long d2 = dx * dx + dy * dy; // long이라야 넘치지 않는다(최대 8×10^10)            if (d2 <= r * r) watered++;            far = Math.max(far, d2);        }        long s = (long) Math.sqrt(far);        while (s * s > far) s--; // 실수 제곱근이 한 칸 어긋나도 바로잡는다        while ((s + 1) * (s + 1) <= far) s++;        if (s * s < far) s++; // 올림        System.out.println(watered);        System.out.println(Math.max(r, s));    }}
C#Main.cs · 28 行
using System;using System.Linq; class Program{    static void Main()    {        long[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToArray();        long x0 = first[0], y0 = first[1], r = first[2];        int n = int.Parse(Console.ReadLine());        int watered = 0;        long far = 0; // 가장 먼 화분까지 거리의 제곱        for (int i = 0; i < n; i++)        {            long[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToArray();            long dx = p[0] - x0, dy = p[1] - y0;            long d2 = dx * dx + dy * dy; // long이라야 넘치지 않는다(최대 8×10^10)            if (d2 <= r * r) watered++;            far = Math.Max(far, d2);        }        long s = (long)Math.Sqrt(far);        while (s * s > far) s--; // 실수 제곱근이 한 칸 어긋나도 바로잡는다        while ((s + 1) * (s + 1) <= far) s++;        if (s * s < far) s++; // 올림        Console.WriteLine(watered);        Console.WriteLine(Math.Max(r, s));    }}
C++main.cpp · 24 行
#include <algorithm>#include <cmath>#include <iostream> int main() {    long long x0, y0, r;    int n;    std::cin >> x0 >> y0 >> r >> n;    int watered = 0;    long long far = 0; // 가장 먼 화분까지 거리의 제곱    for (int i = 0; i < n; i++) {        long long x, y;        std::cin >> x >> y;        long long dx = x - x0, dy = y - y0;        long long d2 = dx * dx + dy * dy; // long long이라야 넘치지 않는다(최대 8×10^10)        if (d2 <= r * r) watered++;        far = std::max(far, d2);    }    long long s = static_cast<long long>(std::sqrt(static_cast<double>(far)));    while (s * s > far) s--; // 실수 제곱근이 한 칸 어긋나도 바로잡는다    while ((s + 1) * (s + 1) <= far) s++;    if (s * s < far) s++; // 올림    std::cout << watered << '\n' << std::max(r, s) << '\n';}
Cmain.c · 24 行
#include <math.h>#include <stdio.h> int main(void) {    long long x0, y0, r;    int n;    scanf("%lld %lld %lld %d", &x0, &y0, &r, &n);    int watered = 0;    long long far = 0; // 가장 먼 화분까지 거리의 제곱    for (int i = 0; i < n; i++) {        long long x, y;        scanf("%lld %lld", &x, &y);        long long dx = x - x0, dy = y - y0;        long long d2 = dx * dx + dy * dy; // long long이라야 넘치지 않는다(최대 8×10^10)        if (d2 <= r * r) watered++;        if (d2 > far) far = d2;    }    long long s = (long long)sqrt((double)far);    while (s * s > far) s--; // 실수 제곱근이 한 칸 어긋나도 바로잡는다    while ((s + 1) * (s + 1) <= far) s++;    if (s * s < far) s++; // 올림    printf("%d\n%lld\n", watered, s > r ? s : r);    return 0;}
Craykonmain.cray · 34 行
first = 控制台.读数字();x0 = first[0];y0 = first[1];r = first[2];n = 控制台.读行().转数字();watered = 0;far = 0; // 가장 먼 화분까지 거리의 제곱循环 (i = 0; i < n; i++){    p = 控制台.读数字();    dx = p[0] - x0;    dy = p[1] - y0;    d2 = dx * dx + dy * dy; // 거듭제곱 연산자가 없으니 곱해서 제곱한다    如果 (d2 <= r * r)    {        watered += 1;    }    far = 数学.较大值(far, d2);}s = 数学.向下取整(数学.平方根(far));当 (s * s > far){    s -= 1; // 실수 제곱근이 한 칸 어긋나도 바로잡는다}当 ((s + 1) * (s + 1) <= far){    s += 1;}如果 (s * s < far){    s += 1; // 올림}控制台.输出(watered);控制台.输出(数学.较大值(r, s));