[NOI online2022普及B] 数学游戏

题目描述
Kri 喜欢玩数字游戏。

一天,他在草稿纸上写下了 \(t\) 对正整数 \((x,y)\),并对于每一对正整数计算出了 \(z=x\times y\times\gcd(x,y)\)

可是调皮的 Zay 找到了 Kri 的草稿纸,并把每一组的 \(y\) 都擦除了,还可能改动了一些 \(z\)

现在 Kri 想请你帮忙还原每一组的 \(y\),具体地,对于每一组中的 \(x\)\(z\),你需要输出最小的正整数 \(y\),使得 \(z=x\times y\times\gcd(x,y)\)。如果这样的 yy 不存在,也就是 Zay 一定改动了 \(z\),那么请输出 \(-1\)

注:\(\gcd(x,y)\) 表示 xx 和 yy 的最大公约数,也就是最大的正整数 \(d\),满足 \(d\) 既是 \(x\) 的约数,又是 \(y\) 的约数。

输入格式
第一行一个整数 ,表示有 \(t\) 对正整数 \(x\)\(z\)

接下来 tt 行,每行两个正整数 \(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\times y\times \gcd(x,y)=10\times 12\times\gcd(10,12)=240\)

【数据范围】

对于 \(20\%\) 的数据,\(t, x, z \le {10}^3\)
对于 \(40\%\) 的数据,\(t \le {10}^3\)\(x \le {10}^6\)\(z \le {10}^9\)
对于另 \(30\%\) 的数据,\(t \le {10}^4\)
对于另 \(20\%\) 的数据,\(x \le {10}^6\)
对于 \(100\%\) 的数据,\(1 \le t \le 5 \times {10}^5\)\(1 \le x \le {10}^9\)\(1 \le z < 2^{63}\)

\(\gcd(x,y)\)\(d\)\(x=ad\),\(y=bd\),\(z=abd^3\)
尝试解出\(d\),现在\(z\)中去掉\(a\)\(z\div x =bd^2\)
利用上\(\gcd(a,b)=1\),\(\gcd(x^2,z\div x)\)就是\(d^2\),开个根就能得到\(d\)
然后用\(z\div x\div d\)就是\(bd\),也就是\(y\)。然后在开根或很多地方可能会出现问题,所以把\(y\)带入式子验证一下。

#include<cstdio> 
#include<cmath>
int t,x;
long long z,y,d;
long long gcd(long long x,long long y)
{
	if(x<y)
		return gcd(y,x);
	if(!y)
		return x;
	return gcd(y,x%y);
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%lld",&x,&z);
		y=z/x;
		d=sqrt(gcd(1LL*x*x,y));
		y=y/d;
		if(x*y*gcd(x,y)!=z)
			printf("-1\n");
		else
			printf("%lld\n",y);
	}
}
posted @ 2022-04-14 18:06  灰鲭鲨  阅读(115)  评论(0编辑  收藏  举报