题意:给出两数的gcd和lcm,求乘积最小的两数。
解法:枚举lcm/gcd的因子,套模版。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define time 12
using namespace std;
int p2[20];
const int C=200;
const long long max1 = (long long)pow((double)2,(double)62) ;
long long min1;
long long cnt, fac[20];
long long gcd(long long x,long long y){
return y==0?x:gcd(y, x%y);
}
long long Mulmode(long long a,long long b,long long c){ //计算(a*b) mod n
long long ret = 0;
while(b){
if(b & 1)
ret = (ret + a) % c;
a = (a << 1) % c;
b = b >> 1;
}
return ret ;
}
long long powmode(long long a,long long b,long long c){ //计算(a^b) mod n
long long ret = 1;
while(b ){
if(b & 1)
ret = Mulmode(ret,a,c);
a = Mulmode(a,a,c);
b = b >> 1;
}
return ret ;
}
bool witness(long long a,long long n){ //以a为基对n进行Miller测试并实现二次探测
long long m,x,y;
int i,j = 0;
m = n - 1;
while(m % 2 == 0){
m = m >> 1;
j ++;
}
x = powmode(a ,m ,n );
for(i = 1;i <= j ;i ++){
y = powmode(x,2,n);
if((y == 1) && (x != 1) && (x != n - 1))
return true;
x = y;
}
if(y != 1)
return true;
return false;
}
bool miller_rabin(long long n ,long long s){
long long a;
int i ;
if(n == 1)
return false ;
if(n == 2)
return true;
if(n % 2 == 0)
return false;
for(i = 1;i <= s; i ++){
a = rand() % (n - 1) + 1;
if(witness(a,n))
return false;
}
return true;
}
long long pollard_rho(long long n ,long long c ){
long long i,k,x,y,d;
i = 1;
k = 2;
x = rand() % n;
y = x;
while(true){
i ++ ;
x = (Mulmode(x, x, n) + c) % n;
d = gcd( y - x , n );
if( d > 1 && d < n ) return d;
if(y == x ) return n;
if(i == k ){
y = x;
k = k << 1;
}
}
}
void get_small(long long n,long long c){
long long m;
if(n == 1)
return;
if(miller_rabin(n,time)){
if(n < min1 )
min1 = n;
return;
}
m = n;
while(m == n )
m = pollard_rho(n, c--);
get_small(m , c);
get_small(n/m, c);
}
int main(){
long long a, b, n, ans;
p2[0]=1;
int i;
for(i=1; i<20; i++)
p2[i]=p2[i-1]*2;
while(scanf("%I64d%I64d",&a, &b)!=EOF){
n=b/a;
cnt=0;
ans=1;
while(n!=1&&!miller_rabin(n, time)){
min1=max1;
get_small(n, C);
fac[cnt]=1;
while(n%min1==0){
fac[cnt]*=min1;
n/=min1;
}
cnt++;
}
if(n>1){
fac[cnt++]=n;
}
n=b/a;
int k=p2[cnt]-1;
while(k>=0){
int t=k;
long long tmp=1;
for(i=0; i<cnt; i++){
if(t&1)
tmp*=fac[i];
t>>=1;
}
if(n/tmp<tmp)tmp=n/tmp;
if(tmp>ans)ans=tmp;
k--;
}
printf("%lld %lld\n", ans*a, n/ans*a);
}
return 0;
}