POJ 2429

开始闲的无聊特判gcd=1的情况 特判错了 真是呵呵诶、

我的做法 比较挫、、首先肯定对gcd 还有 lcm进行质因数Poll分解。

我是用map记录每个因子和出现次数。然后合并两个map所有质数,就是用merge、然后DFS下、、去得到的value里面 使得 value^<=gcd *lcm的最大value赋值给a即可。。b= gcd * lcm /a;

#include <cstdio>
#include <cstring>
#include <map>
#include <iterator>
#include <ctime>
#include <cstdlib>
using namespace std;
#define S 5
typedef long long LL;
map<LL, int>mp[2];
LL gcd, lcm, ans, tot;
LL factor[3000];
LL mods(LL x, LL y, LL n){
 	x %= n;
	y %= n;
	LL tmp = 0;
	while(y){
		if(y & 1)
			tmp = (tmp + x) % n;
		x = (x << 1) % n;
		y >>= 1;
	}
	return tmp;
}
LL pow(LL x, LL y, LL n){
	x %= n;
	LL tmp = 1;
	while(y){
		if(y & 1)tmp = mods(tmp, x, n);
		x = mods(x, x, n);
		y >>= 1;
	}
	return tmp;
}
LL pow(LL x, LL y){
	LL tmp = 1;
	while(y){
		if(y & 1)tmp *= x;
		x *= x;
		y >>=1;
	}
	return tmp;
}
int judge(LL tmp, LL n, LL m, LL cnt){
	LL v = pow(tmp, m, n);
	LL last = v;
	for(LL i = 1; i <= cnt; i++){
		v = mods(v, v, n);
		if(v == 1){
			if(last != 1 && last != n-1)
				return 0;
		}
		last = v;
	}
	if(v == 1)return 1;
	return 0;
}
int miller_rubin(LL n){
	LL m = n - 1;
	LL cnt = 0;
	while(!(m & 1)) cnt++, m >>= 1;
	for(int i = 0; i < S; i++){
		LL tmp = (rand() % (n-1)) +1;
		if(!judge(tmp, n, m, cnt))
			return 0;
	}
	return 1;
}
LL f(LL x, LL n, LL c){
	return (mods(x, x, n) + c)%n;
}
LL Gcd(LL x, LL y){
	return y == 0?x: Gcd(y, x % y);
}
LL poll(LL n, LL c){
	if(!(n & 1))return 2;
	LL x = rand() % n;
	LL y = x;
	LL i = 1;
	LL k = 2;
	while(1){
		x = f(x, n, c);
		LL d = Gcd(y - x + n, n);
		if(d != 1 && d != n)
			return d;
		if(y == x)
			return n;
		i++;
		if(i == k){
			y = x;
			k += k;
		}
	}
}
void find(LL n, int f){
	if(miller_rubin(n)){
		mp[f][n]++;
		return;
	}
	LL p = n;
	while(p >= n) p = poll(p, rand()%(n-1) + 1);
	find(p, f);
	find(n / p, f);
}
void dfs(int i, LL sum){
	if(i >= tot){
		if(lcm / sum >= sum / gcd)
			if(sum > ans)
				ans = sum;
		return; 
	}
	for(int j = 0; j < 2; j++){
		dfs(i+1, sum * pow(factor[i], mp[j][factor[i]]));
	}
}
int main(){
	srand(time(NULL));
	while(scanf("%lld%lld", &gcd, &lcm)!=EOF){
		mp[0].clear();
		mp[1].clear();
		if( gcd == lcm){
			printf("%lld %lld\n",gcd,lcm);
			continue;
		}
		ans = 0;
		tot = 0;
		if(gcd != 1)
		find(gcd,0);
		if(lcm != 1)
		find(lcm,1);
		map<LL,int>::iterator it1 = mp[0].begin(), it2 = mp[1].begin();
		while(it1 != mp[0].end() && it2 != mp[1].end()){
			if(it1->first == it2->first){
				factor[tot++] = it1->first;
				++it1;
				++it2;
			}
			else
				if(it1->first > it2->first){
					factor[tot++] = it2->first;
					++it2;
				}
				else{
					factor[tot++] = it1->first;
					++it1;
				}
		}
		while(it1 != mp[0].end()){
			factor[tot++]=it1->first;
			++it1;
		}
		while(it2 != mp[1].end()){
			factor[tot++]=it2->first;
			++it2;
		}
		dfs(0, 1);
		printf("%lld %lld\n", ans,lcm / ans * gcd); 
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值