POJ/PKU 2429 GCD & LCM
题目说给出最大公约数和最小公倍数,求a,b。如果存在多个解取最小a+b。
思路很简单,a/GCD和b/GCD是互质的,所以a/GCD和b/GCD分解以后产生的因子肯定不同。所以他们的乘积a/GCD*(b/GCD)=a*b/GCD/GCD=LCM/GCD因数分解以后产生的任何一种质因数只能属于a/GCD或b/GCD。很明显种数不会超过15,深搜或者位运算很容易求出所有组合,取其中a+b最小的a,b即可。
质因数分解直接用PollardRho的模板,但是在G++下仍然会re,可能是编译器的原因。
/*
* File: main.cpp
* Author: acmer
*
* Created on June 11, 2011, 3:55 PM
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <algorithm>
using namespace std;
#define Random(n) (rand()%(n+1))
typedef __int64 int64;
const int kMaxT(50);
int cnt;
int64 factor[207];
int64 Gcd(int64 a,int64 b){
for(int64 t=a%b;t;a=b,b=t,t=a%b);
return b>0?b:(b*(-1));
}
int64 MutiMod(int64 a,int64 b,int64 n){
int64 exp(a%n),res(0);
while(b){
if(b&1){
res+=exp;
if(res>n)res-=n;
}
exp<<=1;
if(exp>n)exp-=n;
b>>=1;
}
return res;
}
int64 ExpMod(int64 a,int64 n,int64 b){
int64 r(1),t(a%b);
if(n==0) return 1%b;
while(n>1){
if(n&1)
r=MutiMod(r,t,b);
t=MutiMod(t,t,b);
n>>=1;
}
return MutiMod(r,t,b);
}
bool MillerRabbin(int64 n){
if(n==2)
return true;
if(n<2 || !(n&1))
return false;
int64 a,u(n-1),x,y;
int t(0);
while(u%2==0){
t++;
u>>=1;
}
srand(time(NULL));
for(int i=1;i<=kMaxT;i++){
a=Random(n-2)+1;
x=ExpMod(a,u,n);
for(int j=0;j<t;j++){
y=MutiMod(x,x,n);
if(y==1 && x!=1 && x!=n-1)
return false;
x=y;
}
if(y!=1)
return false;
}
return true;
}
int64 PollardRho(int64 n,int c){
int64 x(Random(n-2)+1),y(x),d,i(1),k(2);
while (true){
i++;
x=(MutiMod(x,x,n)+c)%n;
d=Gcd(y-x,n);
if(d > 1 && d < n)
return d;
if(x==y)
return n;
if(i==k){
y=x;
k<<=1;
}
}
}
int64 temp;
//找出所有质因数
void FindFactor(int64 n, int k){
if(n == 1)
return;
if(MillerRabbin(n)){
//保存小于n的所有质因数
if (n != temp){
factor[cnt++] = n;
}
return;
}
int64 p(n);
while (p >= n)
p = PollardRho(p,k--);
FindFactor(p, k);
FindFactor(n/p,k);
}
int l;
int64 t[67], minf, a, n;
//求最小的a+b
void dfs(int i, int64 sum){
if (i == l + 1){
if (minf > (sum + n / sum)){
minf = sum + n / sum;
a = sum;
}
return;
}
dfs(i+1, sum * t[i]);
dfs(i+1, sum * 1);
return;
}
int main(){
int64 LCM, GCD;
while (cin>>GCD>>LCM){
n = LCM / GCD;
if (n == 1 || MillerRabbin(n)){
cout<<GCD<<" "<<LCM<<endl;
continue;
}
cnt = 0;
temp = n;
FindFactor(n, 107);
sort(factor, factor + cnt);
l = 0;
t[l] = factor[0];
int j = 0;
for (int i = 1; i < cnt; i++)
if (factor[i] == factor[j])
t[l] *= factor[i];
else {
t[++l] = factor[i];
j = i;
}
minf = 2e63;//科学计数法越界以后会自动换为此范围内最大数
dfs(0, 1);
cout<<min(a*GCD, LCM/a)<<" "<<max(a*GCD, LCM/a)<<endl;
}
return 0;
}
浙公网安备 33010602011771号