2020年11月3日提高组【校测】 luogu U138415 堆箱子
Description–
仓库中有很多的箱子,这天小武想把箱子收拾一下。仓库是一个长方体,我们不用考虑仓库的高度,仓库的长度为
N
N
N,宽度为
M
M
M,箱子是一个标准的正方体,边长为
L
L
L。小武很严格,对于箱子的摆放有很严格的要求。小武要求用若干根直线等分仓库的长和宽,而箱子只能放在等分长和宽的直线的交点上,并且一个箱子到四个方向的距离(可能是到另一个箱子, 也可能是到仓库的边缘),必须相同。那么在满足要求的前提下,小武想放心尽可能多的箱子, 那么此时一个箱子到四个方向的距离是多少呢?(设这个距离为
x
x
x)
Input–
一行三个数表示 L , N , M L,N,M L,N,M
Output–
一行一个实数表示距离 x x x,精确到小数点后五位,如果无法满足要求,输出 − 1 -1 −1
Sample Input–
样例1
2 18 13
样例2
4 26 26
样例3
3 46 18
Sample Output–
样例1
0.50000
样例2
0.28571
样例3
0.50000
说明–
样例解释
对于样例
1
1
1,横排放
7
7
7 个箱子,竖排放
5
5
5 个箱子 :
x
=
(
18
−
27
)
/
8
=
(
13
−
25
)
/
6
=
0.50000
x=(18-27)/8=(13-25)/6=0.50000
x=(18−27)/8=(13−25)/6=0.50000
数据范围
对于
24
%
24\%
24% 的数据,
1
≤
L
≤
100
,
1
≤
N
,
M
≤
1000
1≤L≤100,1≤N,M≤1000
1≤L≤100,1≤N,M≤1000
对于
48
%
48\%
48% 的数据,
1
≤
L
≤
1000
,
1
≤
L
,
N
,
M
≤
1
0
6
1≤L≤1000,1≤L,N,M≤10^6
1≤L≤1000,1≤L,N,M≤106
对于
80
%
80\%
80% 的数据,
1
≤
L
≤
1
0
6
1≤L≤10^6
1≤L≤106
对于
100
%
100\%
100% 的数据,
1
≤
L
,
N
,
M
≤
1
0
9
1≤L,N,M≤10^9
1≤L,N,M≤109
解题思路–
将仓库俯视图的长宽分别拓宽
L
L
L
那么每行每列都是由若干个正方形 + 一条线组成(
L
L
L + 线长
x
x
x)
即长宽分别为
(
L
+
x
)
(L+x)
(L+x) 的若干倍
于是问题就转换为求出最小的
(
L
+
x
)
(L+x)
(L+x)
也就是使得
(
M
+
L
)
(M+L)
(M+L) 和
(
N
+
L
)
(N+L)
(N+L) 除以它都能得到整数
那么只要
g
=
g
c
d
(
M
+
L
,
N
+
L
)
g = gcd(M+L,N+L)
g=gcd(M+L,N+L) 除以它是整数即可
假设
g
L
+
x
=
y
\frac{g}{L+x}=y
L+xg=y,即
g
y
=
L
+
x
\frac{g}{y}=L+x
yg=L+x
因为
x
>
0
x>0
x>0
所以就是求满足
g
y
>
=
L
\frac{g}{y}>=L
yg>=L 的最大
y
y
y
所以最大
y
y
y就是
g
L
\frac{g}{L}
Lg下取整
那么答案就是
g
y
−
L
\dfrac{g}{y}-L
yg−L
(
−
L
(-L
(−L是因为
g
y
\frac{g}{y}
yg为最小的
(
L
+
x
)
)
(L+x))
(L+x))
代码–
#include <iostream>
#include <cstdio>
using namespace std;
int l, n, m, a;
double ans;
int gcd(int x, int y)
{
if (!y) return x;
return gcd(y, x % y);
}
int main()
{
scanf("%d%d%d", &l, &n, &m);
a = gcd(n + l, m + l);
if (n < l || m < l || a < l) printf("-1");
else printf("%.5lf", (double)a / (a / l) - l);
return 0;
}