[P8255 NOI Online 2022 普及组] 数学游戏(民间数据) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目: z = xy*gcd(x,y)
已知:z, x 求 y
思路一,暴力20%
直接上代码
#include <iostream>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
LL gcd(LL a, LL b) // 欧几里得算法
{
return b ? gcd(b, a % b) : a;
}
LL solve(LL x, LL z)
{
if (z % x != 0)
{
return -1;
}
else
{
LL y_gcx = z / x;
for (LL i = 1; i <= y_gcx; i++)
{
if (gcd(i, x) * i == y_gcx)
return i;
}
return -1;
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
LL x, z;
cin >> x >> z;
cout << solve(x, z) << endl;
}
return 0;
}
思路二,数学解100%
解: x与y 的最大公约数设为a. 则gcd(x,y) = a.
z
=
x
∗
y
∗
g
c
d
(
x
,
y
)
t
=
z
/
x
=
y
∗
g
c
d
(
x
,
y
)
设
:
x
=
k
∗
a
设
:
y
=
l
∗
a
l
与
k
的
最
大
公
约
数
为
1.
t
1
=
g
c
d
(
x
∗
x
,
y
∗
g
c
d
(
x
,
y
)
)
t
1
=
g
c
d
(
k
∗
a
∗
k
∗
a
,
l
∗
a
∗
a
)
a
=
s
q
r
t
(
t
1
)
t
1
一
定
是
完
全
平
方
数
。
那
么
y
有
一
定
存
在
解
。
且
解
为
t
/
a
;
如
果
不
是
的
话
,
则
y
不
是
整
数
,
无
解
,
返
回
−
1
。
z = x*y*gcd(x,y)\\ t = z/x = y*gcd(x,y)\\ 设: x = k*a\\ 设: y = l*a\\ l与k 的最大公约数为1. \\ t1 = gcd(x*x, y*gcd(x,y))\\ t1 = gcd(k*a*k*a,l*a*a)\\ a = sqrt(t1)\\ t1 一定是完全平方数。那么y有一定存在解。且解为t/a; 如果不是的话,则y不是整数,无解,返回-1。
z=x∗y∗gcd(x,y)t=z/x=y∗gcd(x,y)设:x=k∗a设:y=l∗al与k的最大公约数为1.t1=gcd(x∗x,y∗gcd(x,y))t1=gcd(k∗a∗k∗a,l∗a∗a)a=sqrt(t1)t1一定是完全平方数。那么y有一定存在解。且解为t/a;如果不是的话,则y不是整数,无解,返回−1。
Code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <math.h>
typedef long long LL;
using namespace std;
LL gcd(LL a, LL b) // 欧几里得算法
{
return b ? gcd(b, a % b) : a;
}
LL solve(LL x, LL z)
{
if (z % x != 0)
{
return -1;
}
else
{
LL y_gcx = z / x;
LL tem = gcd(x * x, y_gcx); // 先求出:x*x和y*gcd(x,y)公约数。
LL t = sqrt(tem);//sqrt正常返回double, 如果这个公约数的开方恰好等于一个整数。
if (t * t == tem)// 如果这个公约数的开方恰好等于一个整数。
return y_gcx / t;// 解出y
else
return -1;
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
LL x, z;
cin >> x >> z;
cout << solve(x, z) << endl;
}
return 0;
}