0
点赞
收藏
分享

微信扫一扫

【数学游戏】

前行的跋涉者 2022-04-18 阅读 31

题目描述
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 因 数 ) y
gcd(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;
}

举报

相关推荐

0 条评论