UOJ12 【UER #1】猜数 题解
题目链接:#12. 【UER #1】猜数
题意:
给定一个完全平方数 $n=a\times b=g \times l$ ,其中 $a,b,g,l$ 均为正整数。
每次给出 $g,l$ ,求 $a + b$ 的最小值和最大值,保证 $g \mid a$ 且 $g \mid b$ 。
根据均值不等式,有 $a + b \ge 2\sqrt{ab} = 2\sqrt{n}$ 。
由于 $n=gl$ 是完全平方数,我们可以求得 $\sqrt{n}$ 的值,得到 $a + b$ 的下界,当 $a=b=\sqrt{n}$ 时等号成立。
那么当 $g \mid a,~g\mid b$ 时还能取到等号吗?
设 $a = a_0g,~b = b_0g$ ,则 $n = a_0b_0g^2$ ,则 $l = a_0b_0g$ ,故 $g \mid l$ 。
设 $l = kg$ ,则 $gl = kg^2$ 为完全平方数,故 $k$ 也为完全平方数。
设 $k=t^2$ ,则 $l = t^2g$ ,那么 $a = b = \sqrt{n} = tg$ ,是 $g$ 的倍数,那么等号可以取到,最小值得到。
考虑最大值,由于 $a + b = a + \frac{n}{a}$ ,显然这是一个在 $[g,l]$ 上的对勾函数,如下图所示:
那么当 $a=g$ 或 $a=l$ 时取到最大值,此时 $a + b = g + l$ ,且显然有 $g \mid a, g\mid b$ 。
注意这道题的 $g,l$ 非常大,可以利用 $g \mid l$ ,那么 $\sqrt{gl} = tg = \sqrt{t^2}g = g\sqrt{\frac{l}{g}}$ 求根号。
实际上不一定要 $g \mid l$ ,设求 $\sqrt{xy}$ ($\sqrt{xy}$ 是整数)记 $d = \gcd(x, y),~x = x_0d,y = y_0 d$ 。
那么此时显然 $\gcd(x_0, y_0) =1$ 。显然 $x_0,y_0$ 都是完全平方数,直接分别开方后乘上 $d$ 即可
时间复杂度 $\mathcal{O}(T \log V)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define rep(i, a, b) for(int i = (a), i##END = (b); i <= i##END; i++)
#define Rep(i, a, b) for(int i = (a), i##END = (b); i >= i##END; i--)
#define N ((int)())
int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }
int sqrt(int x, int y)
{
int d = gcd(x, y), m = sqrtl(x / d), n = sqrtl(y / d);
return d * n * m;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
int qwq; cin >> qwq; while(qwq--)
{
static int a, b; cin >> a >> b;
cout << sqrt(a, b) * 2 << ' ' << a + b << '\n';
}
return 0;
}
参考文献:
[1] https://yhx-12243.github.io/OI-transit/records/uoj12.html