题意:
T 组 测 试 数 据 , T组测试数据, T组测试数据,
每 组 包 括 两 个 正 整 数 , 分 别 表 示 一 个 最 大 公 约 数 G 和 最 小 公 倍 数 L 。 每组包括两个正整数,分别表示一个最大公约数G和最小公倍数L。 每组包括两个正整数,分别表示一个最大公约数G和最小公倍数L。
要 求 输 出 满 足 条 件 的 a 和 b , 使 得 g c d ( a , b ) = G , l c m ( a , b ) = L 。 要求输出满足条件的a和b,使得gcd(a,b)=G,lcm(a,b)=L。 要求输出满足条件的a和b,使得gcd(a,b)=G,lcm(a,b)=L。
若 无 解 , 输 出 − 1 。 若无解,输出-1。 若无解,输出−1。
若 有 多 组 解 , 输 出 a 最 小 的 一 组 解 。 若有多组解,输出a最小的一组解。 若有多组解,输出a最小的一组解。
Sample Input
2
1 2
3 4
Sample Output
1 2
-1
数据范围:
T ≤ 100 , G 和 L 不 超 过 2 31 T\le100,G和L不超过2^{31} T≤100,G和L不超过231
Time limit: 1000 ms
分析:
由 题 意 , 根 据 a 和 b 的 最 大 公 约 数 和 最 小 公 倍 数 , 反 过 来 求 a 和 b 。 由题意,根据a和b的最大公约数和最小公倍数,反过来求a和b。 由题意,根据a和b的最大公约数和最小公倍数,反过来求a和b。
我 们 知 道 : 我们知道: 我们知道:
设 a = P 1 a 1 P 2 a 2 . . . P k a k , b = P 1 b 1 P 2 b 2 . . . P k b k 设a=P_1^{a_1}P_2^{a_2}...P_k^{a_k},b=P_1^{b_1}P_2^{b_2}...P_k^{b_k} 设a=P1a1P2a2...Pkak,b=P1b1P2b2...Pkbk
则 : 则: 则:
g c d ( a , b ) = P 1 m i n ( a 1 , b 1 ) P 2 m i n ( a 2 , b 2 ) . . . P k m i n ( a k , b k ) \qquad gcd(a,b)=P_1^{min(a_1,b_1)}P_2^{min(a_2,b_2)}...P_k^{min(a_k,b_k)} gcd(a,b)=P1min(a1,b1)P2min(a2,b2)...Pkmin(ak,bk)
l c m ( a , b ) = P 1 m a x ( a 1 , b 1 ) P 2 m a x ( a 2 , b 2 ) . . . P k m a x ( a k , b k ) \qquad lcm(a,b)=P_1^{max(a_1,b_1)}P_2^{max(a_2,b_2)}...P_k^{max(a_k,b_k)} lcm(a,b)=P1max(a1,b1)P2max(a2,b2)...Pkmax(ak,bk)
可 知 , 对 于 任 意 两 个 整 数 数 x , y , 设 它 们 的 质 因 子 P i 的 指 数 分 别 为 u i 和 v i , 可知,对于任意两个整数数x,y,设它们的质因子P_i的指数分别为u_i和v_i, 可知,对于任意两个整数数x,y,设它们的质因子Pi的指数分别为ui和vi,
只 要 满 足 数 对 ( u i , v i ) = ( a i , b i ) 或 ( u i , v i ) = ( b i , a i ) , 就 能 够 找 到 满 足 条 件 的 一 组 解 ( x , y ) 只要满足数对(u_i,v_i)=(a_i,b_i)或(u_i,v_i)=(b_i,a_i),就能够找到满足条件的一组解(x,y) 只要满足数对(ui,vi)=(ai,bi)或(ui,vi)=(bi,ai),就能够找到满足条件的一组解(x,y)
上述讨论是在有解的情形下讨论的。下面简要说明无解情况:
设 G = P 1 g 1 P 2 g 2 . . . P k g k , L = P 1 l 1 P 2 l 2 . . . P k l k 设G=P_1^{g_1}P_2^{g_2}...P_k^{g_k},L=P_1^{l_1}P_2^{l_2}...P_k^{l_k} 设G=P1g1P2g2...Pkgk,L=P1l1P2l2...Pklk
当 g i > l i 时 , 可 知 , 无 法 找 到 一 组 符 合 条 件 的 x , y , 使 得 m i n ( u i , l i ) = g i , m a x ( u i , l i ) = l i , 当g_i>l_i时,可知,无法找到一组符合条件的x,y,使得min(u_i,l_i)=g_i,max(u_i,l_i)=l_i, 当gi>li时,可知,无法找到一组符合条件的x,y,使得min(ui,li)=gi,max(ui,li)=li,
此 时 是 无 解 情 况 。 此时是无解情况。 此时是无解情况。
那么如何确定最小解?
当 给 定 的 数 据 有 解 时 , 说 明 对 于 任 意 一 组 g i , l i , 都 有 g i ≤ l i , 当给定的数据有解时,说明对于任意一组g_i,l_i,都有g_i\le l_i, 当给定的数据有解时,说明对于任意一组gi,li,都有gi≤li,
我 们 要 输 出 a 最 小 的 解 , a 最 小 即 最 大 公 约 数 G , 此 时 b 也 唯 一 确 定 , 即 最 小 公 倍 数 。 我们要输出a最小的解,a最小即最大公约数G,此时b也唯一确定,即最小公倍数。 我们要输出a最小的解,a最小即最大公约数G,此时b也唯一确定,即最小公倍数。
具体落实代码:
① 、 对 输 入 的 G 和 L 进 行 因 数 分 解 , 用 一 个 同 一 个 数 组 存 储 质 因 子 , 用 两 个 数 组 分 别 存 储 对 应 的 指 数 。 ①、对输入的G和L进行因数分解,用一个同一个数组存储质因子,用两个数组分别存储对应的指数。 ①、对输入的G和L进行因数分解,用一个同一个数组存储质因子,用两个数组分别存储对应的指数。
② 、 若 G 和 L 中 , 存 在 某 个 质 因 子 的 指 数 g i > l i , 则 无 解 , 否 则 输 出 G 和 L 。 ②、若G和L中,存在某个质因子的指数g_i>l_i,则无解,否则输出G和L。 ②、若G和L中,存在某个质因子的指数gi>li,则无解,否则输出G和L。
由 于 G , L ≤ 2 31 , 我 们 仅 需 预 处 理 到 2 31 的 质 数 即 可 。 由于G,L\le 2^{31},我们仅需预处理到\sqrt{2^{31}}的质数即可。 由于G,L≤231,我们仅需预处理到231的质数即可。
时 间 复 杂 度 O ( G ) 时间复杂度O(\sqrt{G}) 时间复杂度O(G)
代码:
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N=65536;
int primes[N+10], idx;
int divisors[32], s[3][32], cnt;
bool st[N+10];
void get_prime(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[idx++]=i;
for(int j=0;primes[j]*i<=n;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
void get_divisors(int a,int b)
{
int sqa=sqrt(a), sqb=sqrt(b);
for(int i=0;primes[i]<=max(sqa,sqb);i++)
{
int p=primes[i];
if(a%p==0||b%p==0)
{
divisors[cnt]=p;
int k1=0, k2=0;
while(a%p==0)
{
k1++;
a/=p;
}
while(b%p==0)
{
k2++;
b/=p;
}
s[1][cnt]=k1;
s[2][cnt++]=k2;
}
}
if(a>1||b>1)
{
if(a==b) divisors[cnt]=a, s[1][cnt]=s[2][cnt]=1, cnt++;
else
{
if(a>1) divisors[cnt]=a, s[1][cnt]=1, s[2][cnt++]=0;
if(b>1) divisors[cnt]=b, s[1][cnt]=0, s[2][cnt++]=1;
}
}
}
int main()
{
get_prime(N);
int T;
int a,b;
cin>>T;
while(T--)
{
cnt=0;
memset(divisors,0,sizeof divisors);
memset(s,0,sizeof s);
cin>>a>>b;
get_divisors(a,b);
bool flag=true;
ll res1=a, res2=b;
for(int i=0;i<cnt;i++)
if(s[1][i]>s[2][i])
{
flag=false;
break;
}
if(!flag) puts("-1");
else printf("%lld %lld\n",res1,res2);
}
return 0;
}