POJ 2429 GCD & LCM Inverse (整数分解,由gcd+lcm求a,b)
2012-02-26 17:14
519 查看
题意:给你两个数a,b的最大公约数和最小公倍数,求a,b。(有多组a,b的情况下取a+b最小的)
题解:令 c = a * b / gcd(a,b),对 c 因式分解
假如c = p1^k1 * p2^k2 * p3^k3
令 d1 = p1^k1, d2 = p2^k2, d3 = p3^k3
然后从d1,d2,d3中选取某几项,使得它们的积 s 最接近sqrt(c),且<=sqrt(c)
那么 a = s * gcd(a,b), b = c / s * gcd(a,b)
题解:令 c = a * b / gcd(a,b),对 c 因式分解
假如c = p1^k1 * p2^k2 * p3^k3
令 d1 = p1^k1, d2 = p2^k2, d3 = p3^k3
然后从d1,d2,d3中选取某几项,使得它们的积 s 最接近sqrt(c),且<=sqrt(c)
那么 a = s * gcd(a,b), b = c / s * gcd(a,b)
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<ctime> #include<algorithm> using namespace std; #define lint __int64 lint ans[1000], cnt; lint G, L, a, b, sq; lint gcd(lint a,lint b) { if ( b == 0 ) return a; return gcd ( b, a % b ); } lint mod_mult ( lint a, lint b, lint n ) { lint ret = 0; a = a % n; while ( b >= 1 ) { if ( b & 1 ) { ret += a; if ( ret >= n ) ret -= n; } a = a << 1; if ( a >= n ) a -= n; b = b >> 1; } return ret; } lint mod_exp ( lint a, lint b, lint n ) { lint ret = 1; a = a % n; while ( b >= 1 ) { if ( b & 1 ) ret = mod_mult(ret,a,n); a = mod_mult(a,a,n); b = b >> 1; } return ret; } bool witness ( lint a, lint n ) { int i, t = 0; lint m = n - 1, x, y; while ( m % 2 == 0 ) { m >>= 1; t++; } x = mod_exp (a, m, n); for ( i = 1; i <= t; i++ ) { y = mod_exp ( 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 ( lint n, int times = 10 ) { if ( n == 2 ) return true; if ( n == 1 || n % 2 == 0 ) return false; srand ( time(NULL) ); for ( int i = 1; i <= times; i++ ) { lint a = rand() % (n-1) + 1; if ( witness(a,n) ) return false; } return true; } lint rho ( lint n, int c ) { lint i, k, x, y, d; srand ( time(NULL) ); i = 1; k = 2; y = x = rand() % n; while ( true ) { i++; x = (mod_mult(x,x,n)+c) % n; d = gcd ( y - x, n ); if ( d > 1 && d < n ) return d; if ( y == x ) break; if ( i == k ) { y = x; k *= 2; } } return n; } void pollard ( lint n, int c ) { if ( n == 1 ) return; if ( miller_rabin(n) ) { ans[cnt++] = n; return; } lint m = n; while ( m >= n ) m = rho ( m, c-- ); pollard ( m, c ); pollard ( n / m, c ); } void choose ( lint s, lint val ) { if ( s >= cnt ) { if ( val > a && val <= sq ) a = val; return; } choose ( s + 1, val ); choose ( s + 1, val * ans[s] ); } int main() { while ( scanf("%I64d%I64d",&G,&L) != EOF ) { if ( L == G ) { printf("%I64d %I64d\n",L,G); continue; } L /= G; cnt = 0; pollard ( L, 107 ); sort ( ans, ans + cnt ); int i, j = 0; for ( i = 1; i < cnt; i++ ) { while ( ans[i-1] == ans[i] && i < cnt ) ans[j] *= ans[i++]; if ( i < cnt ) ans[++j] = ans[i]; } cnt = j + 1; a = 1; sq = (lint)sqrt(L+0.0); choose ( 0, 1 ); printf("%I64d %I64d\n", a*G, L/a*G); } return 0; }
相关文章推荐
- POJ2429 GCD&LCM Inverse(整数分解,由GCD+LCM求a,b)
- POJ2429_GCD & LCM Inverse【Miller Rabin素数测试】【Pollar Rho整数分解】
- POJ2429 GCD & LCM Inverse (大整数分解)
- POJ 2429 GCD & LCM Inverse (Pollard rho整数分解+dfs枚举)
- GCD & LCM Inverse POJ - 2429(Pollard rho整数分解+dfs)
- POJ 2429 GCD & LCM Inverse(大整数素因子分解+二进制枚举)
- POJ 2429 GCD & LCM Inverse Pollard Rho大数分解法
- 2429 GCD & LCM Inverse 大整数分解质因数
- poj 2429 GCD & LCM Inverse(Miller_rabin 测试+pollard_rho大数分解)
- POJ:2429-GCD & LCM Inverse(素数判断神题)(Millar-Rabin素性判断和Pollard-rho因子分解)
- poj2429 GCD & LCM Inverse 因数分解pollard_rho算法
- POJ 2429 GCD & LCM Inverse (大整数素性测试与因式分解)
- GCD & LCM Inverse POJ - 2429 Pollard_rho大数因子分解
- POJ 2429 GCD &amp; LCM Inverse(大数分解)
- POJ 2429 GCD & LCM Inverse(素数判定Miller-Rabin+素因子分解Pollard-rho)
- poj 2429 GCD & LCM Inverse(拉宾米勒测试+大数分解+dfs)
- poj 2429 GCD & LCM Inverse 【java】+【数学】
- POJ 2429 GCD & LCM Inverse(Pollard_Rho+dfs)
- POJ, 2429 GCD & LCM Inverse
- poj 2429 GCD & LCM Inverse