poj2429 GCD & LCM Inverse

用miller_rabin 和 pollard_rho对大数因式分解,再用dfs寻找答案即可。

http://poj.org/problem?id=2429

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 using namespace std;
  6 typedef __int64 LL;
  7 const int maxn = 100;
  8 const int times = 10;
  9 LL prime[maxn], k;
 10 int cnt[maxn];
 11 LL c, d, pm, mid;
 12
 13 void dfs(int pos, LL t){
 14     if(pos == k){
 15         if(pm < t) pm = t;
 16         return;
 17     }
 18     LL tem = 1;
 19     int c = cnt[pos];
 20     while(c--) tem *= prime[pos];
 21     dfs(pos + 1, t);
 22     if(t * tem <= mid) dfs(pos + 1, t * tem);
 23 }
 24
 25 LL random(LL n){
 26     return (double)rand() / RAND_MAX * n + 0.5;
 27 }
 28
 29 LL multi(LL a, LL b, LL mod){
 30     a %= mod, b %= mod;
 31     LL ans = 0;
 32     while(b){
 33         if(b & 1) ans += a, ans %= mod;
 34         b >>= 1;
 35         a <<= 1;
 36         a %= mod;
 37     }
 38     return ans;
 39 }
 40
 41 LL power(LL a, LL p, LL mod){
 42     a %= mod;
 43     LL ans = 1;
 44     while(p){
 45         if(p & 1) ans = multi(ans, a, mod), ans %= mod;
 46         p >>= 1;
 47         a = multi(a, a, mod);
 48         a %= mod;
 49     }
 50     return ans;
 51 }
 52
 53 LL gcd(LL a, LL b){
 54     if(!b) return a;
 55     return gcd(b, a % b);
 56 }
 57
 58 bool witness(LL a, LL n){
 59     LL u = n - 1;
 60     while(!(u & 1)) u >>= 1;
 61     LL t = power(a, u, n);
 62     while(u != n - 1 && t != 1 && t != n - 1){
 63         t = multi(t, t, n);
 64         u <<= 1;
 65     }
 66     return t == n - 1 || u & 1;
 67 }
 68
 69 bool miller_rabin(LL n){
 70     if(n == 2) return 1;
 71     if(n < 2 || !(n & 1)) return 0;
 72     for(int i = 0; i < times; i++){
 73         LL p = random(n - 2) + 1;
 74         if(!witness(p, n)) return 0;
 75     }
 76     return 1;
 77 }
 78
 79 LL pollard_rho(LL n, LL t){
 80     LL x = random(n - 2) + 1;
 81     LL y = x, i = 1, k = 2, d;
 82     while(1){
 83         ++i;
 84         x = (multi(x, x, n) + t) % n;
 85         d = gcd(y - x, n);
 86         if(1 < d && d < n) return d;
 87         if(x == y) return n;
 88         if(i == k){
 89             y = x;
 90             k <<= 1;
 91         }
 92     }
 93 }
 94
 95 void solve(){
 96     LL m = d / c;
 97     LL m1 = m;
 98     mid = (LL)sqrt(m);
 99     k = 0;
100     memset(cnt, 0, sizeof cnt);
101     if(m % 2 == 0){
102         prime[k++] = 2;
103         while(m % 2 == 0) m >>= 1, ++cnt[k - 1];
104     }
105     while(!miller_rabin(m) && m > 1){
106         int seed = 12312;
107         LL p1 = m;
108         while(p1 >= m || !miller_rabin(p1)) p1 = pollard_rho(m, seed--);
109         prime[k++] = p1;
110         while(m % p1 == 0) m /= p1, ++cnt[k - 1];
111     }
112     if(m != 1) prime[k++] = m, ++cnt[k - 1];
113     pm = 1;
114     dfs(0, 1);
115     LL qm = m1 / pm;
116     printf("%I64d %I64d\n", pm * c, qm * c);
117 }
118
119 int main(){
120     //freopen("in.txt", "r", stdin);
121     //freopen("out.txt", "w", stdout);
122     while(~scanf("%I64d%I64d", &c, &d)) solve();
123     return 0;
124 }

时间: 2024-08-06 14:37:53

poj2429 GCD & LCM Inverse的相关文章

POJ 2429 GCD &amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem?id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63).求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解,形成a^x1 * b^x2 * c^x3-- 的形式,其中a,b,c为互不相同的质数.然后暴力枚举即可. 代码: #include<map> #include<set> #include<queue>

poj 2429 GCD &amp; LCM Inverse 【java】+【数学】

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9928   Accepted: 1843 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a a

POJ5429 GCD &amp; LCM Inverse

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9913   Accepted: 1841 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a a

POJ 2429 GCD &amp; LCM Inverse

设答案为ans1,ans2 ans1=a1*gcd,ans2=a2*gcd,a1,a2互质 gcd*a1*b1=lcm,gcd*a2*b2=lcm a1*b1=lcm=(ans1*ans2)/gcd=a1*a2 综上所诉,a1=b2,a2=b1. 也就是说,ans1=gcd*k1,ans2=gcd*k2 要求k1,k2尽量接近,并且k1,k2互质,并且,k2*k2=lcm/gcd 需要用到Pollard_rho分解质因数,然后暴力搜索寻找k1,k2.用了kuangbin大神的Pollard_rh

POJ 2429 GCD &amp; LCM Inverse(Pollard_Rho+dfs)

[题目链接] http://poj.org/problem?id=2429 [题目大意] 给出最大公约数和最小公倍数,满足要求的x和y,且x+y最小 [题解] 我们发现,(x/gcd)*(y/gcd)=lcm/gcd,并且x/gcd和y/gcd互质 那么我们先利用把所有的质数求出来Pollard_Rho,将相同的质数合并 现在的问题转变成把合并后的质数分为两堆,使得x+y最小 我们考虑不等式a+b>=2sqrt(ab),在a趋向于sqrt(ab)的时候a+b越小 所以我们通过搜索求出最逼近sqr

poj 2429 GCD &amp; LCM Inverse miller_rabin素数判定和pollard_rho因数分解

题意: 给gcd(a,b)和lcm(a,b),求a+b最小的a和b. 分析: miller_rabin素数判定要用费马小定理和二次探测定理.pollard_rho因数分解算法导论上讲的又全又好,网上的资料大多讲不清楚. 代码: //poj 2429 //sep9 #include <iostream> #include <map> #include <vector> #define gcc 10007 #define max_prime 200000 using nam

GCD &amp; LCM Inverse POJ 2429(Pollard Rho质因数分解)

原题 题目链接 题目分析 这道题用Pollard Rho算法不能交G++,会RE!!!先说一下整体思路,gcd指gcd(a,b),lcm指lcm(a,b).a=x*gcd,b=y*gcd,则x,y互质且有x*y=lcm/gcd,要使a+b最小,也就是x+y最小.这里可以看出我们要做的就是分解lcm/gcd的质因子,然后枚举找出最小的x+y,最后输出a*x,a*y.这里还需要注意一下,题目是要求先输出小的再输出大的.至于Pollard Rho算法这里不讲. 代码 1 #include <cstdi

【poj 2429】GCD &amp; LCM Inverse (Miller-Rabin素数测试和Pollard_Rho_因数分解)

本题涉及的算法个人无法完全理解,在此提供两个比较好的参考. 原理 代码实现 个人改编的AC代码: #include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; #define ll long long int top; const

POJ 2429 GCD &amp;amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem? id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63). 求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解.形成a^x1 * b^x2 * c^x3-- 的形式.当中a,b,c为互不同样的质数.然后暴力枚举就可以. 代码: #include<map> #include<set> #include<queue&