题目描述
Kri 喜欢玩数字游戏。
一天,他在草稿纸上写下了 t 对正整数 (x,y),并对于每一对正整数计算出了 z=x×y×gcd(x,y)。
可是调皮的 Zay 找到了 Kri 的草稿纸,并把每一组的 y 都擦除了,还可能改动了一些 z。
现在 Kri 想请你帮忙还原每一组的 y,具体地,对于每一组中的 x 和 z,你需要输出最小的正整数 y,使得 z=x×y×gcd(x,y)。如果这样的 y 不存在,也就是 Zay 一定改动了 z,那么请输出 −1。
注:gcd(x,y) 表示 x 和 y 的最大公约数,也就是最大的正整数 d,满足 d 既是 x 的约数,又是 y 的约数。
输入格式
第一行一个整数 ,表示有 t 对正整数 x 和 z。
接下来 t 行,每行两个正整数 x 和 z,含义见题目描述。
输出格式
对于每对数字输出一行,如果不存在满足条件的正整数 y,请输出 −1,否则输出满足条件的最小正整数 y。
输入输出样例
输入 #1
1
10 240
输出 #1
12
输入 #2
3
5 30
4 8
11 11
输出 #2
6
-1
1
输入 #3
见附件中的 math3.in
输出 #3复制
见附件中的 math3.out
输入 #4
见附件中的 math4.in
输出 #4
见附件中的 math4.out
说明/提示
【样例 1 解释】
x×y×gcd(x,y) = 10×12×gcd(10,12) = 240。
【数据范围】
对于 20% 的数据,t,x,z ≤ 。
对于 40% 的数据,t ≤ ,x ≤
,z ≤
。
对于另 30% 的数据,t ≤ 。
对于另 20% 的数据,x ≤ 。
对于 100% 的数据,1 ≤ t ≤ 5 × ,1 ≤ x ≤
,1 ≤ z <
。
附件下载
math.zip1.62MB
代码 :
cpp
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
int gcd(int x,int y){return x==0?y:gcd(y%x,x);}
int mul(int x,int y,int m){
int r = 0;
while (y) {
if (y&1) r = (r+x)%m;
y >>= 1,x = (x+x)%m;
}
return r;
}
inline void write(int x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
inline int read() {
register int x = 0, t = 1;
register char ch = getchar();
while (ch < '0' || ch > '9') {
if(ch == '-') t -= 1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * t;
}
signed main(){
int T;
cin >> T;
while (T --){
int x,y,z,t,u;
x = read(), z = read();
u = mul(mul(x,x,z),x,z),t = sqrtl((long double)x*gcd(z,u)+0.5),y = z/t;
if (z != x*y*gcd(x,y)) puts("-1");
else {
write(y);
puts("");
}
}
return 0;
}