题目描述
Kri 喜欢玩数字游戏。
一天,他在草稿纸上写下了t tt对正整数( x , y ) (x,y)(x,y),并对于每一对正整数计算出了z = x ∗ y ∗ g c d ( x , y ) z=xygcd(x,y)z=x∗y∗gcd(x,y)。
可是调皮的Zay找到了Kri的草稿纸,并把每一组的y yy都擦除了,还可能改动了一些z zz。
现在Kri想请你帮忙还原每一组的y yy,具体地,对于每一组中的x xx和z zz,你需要输出最小的正整数y yy,使得z = x ∗ y ∗ g c d ( x , y ) z=xygcd(x,y)z=x∗y∗gcd(x,y)。如果这样的y yy不存在,也就是Zay一定改动了z zz,那么请输出− 1 -1−1。
注:g c d ( x , y ) gcd(x,y)gcd(x,y)表示x xx和y yy的最大公约数,也就是最大的正整数d dd,满足d dd既是x xx的约数,又是y yy的约数。
输入格式
第一行一个整数,表示有t tt对正整数x xx和y yy。
接下来t tt行,每行两个正整数x xx和y yy,含义见题目描述。
输出格式
对于每对数字输出一行,如果不存在满足条件的正整数y yy,请输出− 1 -1−1,否则输出满足条件的最小正整数y yy.
样例
样例输入
3
5 30
4 8
11 11
样例输出
6
-1
1
数据范围
对于20 % 20%20%的数据,t , x , z ≤ 1 0 3 t,x,z\leq10^3t,x,z≤10
3
。
对于40 % 40%40%的数据,t ≤ 1 0 3 , x ≤ 1 0 6 , z ≤ 1 0 9 t\leq103,x\leq106,z\leq10^9t≤10
3
,x≤10
6
,z≤10
9
。
对于另30 % 30%30%的数据,t ≤ 1 0 4 t\leq10^4t≤10
4
。
对于另20 % 20%20%的数据,x ≤ 1 0 6 x\leq10^6x≤10
6
。
对于100 % 100%100%的数据,1 ≤ t ≤ 5 ∗ 1 0 5 , 1 ≤ z ≤ 2 63 1\leq t\leq5*10^5,1\leq z\leq2^{63}1≤t≤5∗10
5
,1≤z≤2
63
。
分析
首先可以简单地推出y ∗ g c d ( x , y ) = z x ygcd(x,y)=\frac{z}{x}y∗gcd(x,y)=
x
z
,而z zz和x xx是已知变量,所以可以通过枚举y yy或g c d ( x , y ) gcd(x,y)gcd(x,y)来判断,肯定是枚举g c d ( x , y ) gcd(x,y)gcd(x,y)更快,由于g c d ( x , y ) gcd(x,y)gcd(x,y)一定是x xx的因数,于是我们可以枚举x xx的因数来枚举g c d ( x , y ) gcd(x,y)gcd(x,y),然后根据推出的式子进一步下推来推出判断式。
y ∗ g c d ( x , y ) = z x y = z x ∗ g c d ( x , y ) g c d ( x , z x ∗ g c d ( x , y ) ) = j ( j 即 枚 举 的 x 因 数 ) ygcd(x,y)=\frac{z}{x}\ y=\frac{z}{xgcd(x,y)}\ gcd(x,\frac{z}{xgcd(x,y)})=j(j即枚举的x因数)y∗gcd(x,y)=
x
z
y=
x∗gcd(x,y)
z
gcd(x,
x∗gcd(x,y)
z
)=j(j即枚举的x因数)
这个算法大概是O ( t x ) O(t\sqrt{x})O(t
x
)的时间复杂度,显然不能过,大概能水到40分。
以上是我考试时的思路。
正解如下:
设d = g c d ( x , y ) d=gcd(x,y)d=gcd(x,y),x = p ∗ d x=pdx=p∗d,y = p ∗ d y=pdy=p∗d,则有
z = x ∗ y ∗ d z = p ∗ q ∗ d 3 z x = p ∗ q ∗ d 3 p ∗ d = q ∗ d 2 已 知 x = p ∗ d , z = p ∗ q ∗ d 3 , 求 y y = p d = ( p ∗ q ∗ d 3 ) / ( p ∗ d ) / d 即 y = z x ∗ 1 d 只 需 求 出 d 即 可 因 为 d = g c d ( x , y ) , 所 以 p 与 q 互 质 , 所 以 p 2 与 q 互 质 d 2 = g c d ( p 2 ∗ d 2 , q ∗ d 2 ) = g c d ( x 2 , z x ) d = g c d ( x 2 , z x ) z=xyd\ z=pqd^3\ \frac{z}{x}=\frac{pqd3}{p*d}=q*d2\ 已知x=pd,z=pqd^3,求y\ y=pd=(pqd^3)/(pd)/d\ 即y=\frac{z}{x}\frac{1}{d}\ 只需求出d即可\ 因为d=gcd(x,y),所以p与q互质,所以p^2与q互质\ d2=gcd(p2d2,q*d2)=gcd(x^2,\frac{z}{x})\ d=\sqrt{gcd(x^2,\frac{z}{x})}z=x∗y∗d
z=p∗q∗d
3
x
z
p∗d
p∗q∗d
3
=q∗d
2
已知x=p∗d,z=p∗q∗d
3
,求y
y=pd=(p∗q∗d
3
)/(p∗d)/d
即y=
x
z
∗
d
1
只需求出d即可
因为d=gcd(x,y),所以p与q互质,所以p
2
与q互质
d
2
=gcd(p
2
∗d
2
,q∗d
2
)=gcd(x
2
,
x
z
)
d=
gcd(x
2
,
x
z
)
你以为已经完了吗?
不!
不然它给你-1干嘛
所以,我们还需要判断是否合法。
分析一下,以上方法是否有漏洞。
很明显,真相只有一——
啊不,两个。
首先,g c d ( x 2 , z x ) \sqrt{gcd(x^2,\frac{z}{x})}
gcd(x
2
,
x
z
)
的这个根号
很不行!
根号下的数不一定能开出整数,于是就会出现这样的情况:
我们算出的d ′ = g c d ( x 2 , z x ) = ⌊ g c d ( x 2 , z x ) ⌋ d’=\sqrt{gcd(x2,\frac{z}{x})}=\lfloor\sqrt{gcd(x2,\frac{z}{x})}\rfloord
′
gcd(x
2
,
x
z
)
=⌊
gcd(x
2
,
x
z
)
⌋
而真正的d = g c d ( x 2 , z x ) d=\sqrt{gcd(x^2,\frac{z}{x})}d=
gcd(x
2
,
x
z
)
所以d ′ ≠ d d’\neq dd
′
=d
所以只有当算出来的d ′ d’d
′
等于真正的d dd时,才有答案。
而当真正的d dd等于d ′ d’d
′
的时候,d = g c d ( x , y ) = g c d ( x , z / x / d ′ ) d=gcd(x,y)=gcd(x,z/x/d’)d=gcd(x,y)=gcd(x,z/x/d
′
)
所以判断条件就应该是⌊ d ′ ⌋ \lfloor d’\rfloor⌊d
′
⌋是否等于d ′ d’d
′
其次
谁说z zz一定整除x xx了?
第二个条件就显而易见了:
当z % x = = 0 z%x0z%x0时,输出− 1 -1−1.
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL t,x,z;
LL gcd(LL aa,LL bb)
{
if(!bb) return aa;
return gcd(bb,aa%bb);
}
int main()
{
scanf("%lld",&t);
for(int i=1;i<=t;i++)
{
scanf("%lld%lld",&x,&z);
if(z%x!=0)
{
printf("-1\n");
continue;
}
double d=sqrt(gcd(x*x,z/x)*1.0);
if(floor(d)==d) printf("%lld\n",z/x/(long long)d);
else printf("-1\n");
}
return 0;
}