POJ2429 GCD & LCM Inverse pollard_rho integer factorization

 

Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a and b. But what about the inverse? That is: given GCD and LCM, finding a and b.

Input

The input contains multiple test cases, each of which contains two positive integers, the GCD and the LCM. You can assume that these two numbers are both less than 2^63.

Output

For each test case, output a and b in ascending order. If there are multiple solutions, output the pair with smallest a + b.

Sample Input

3 60

Sample Output

12 15

 

 

Meaning of the questions: given the greatest common divisor and least common multiple of two numbers, allow you to find out the number two conditions are met, and to make their minimum.

 

answer:

For two numbers a, b, and their least common multiple and the greatest common divisor gcd lcm, there lcm = a * b / gcd, further modification can be obtained: (a / gcd * b / gcd) * gcd = lcm, i.e., (a / gcd * b / gcd) = lcm / gcd, we set m = a / gcd, n = b / gcd, then the question becomes: two integer prime to identify the product of their key = lcm / gcd. We can use the integer factorization method pollard_rho find out all prime factors of lcm / gcd then dfs find the product of any of several prime factors (set X), set y = key / x, find the minimum of x + y on the line

 

Code:

  1 #include <cstdio>
  2 
  3 #include <iostream>
  4 
  5 #include <cstdlib>
  6 
  7 #include <cmath>
  8 
  9 #include <algorithm>
 10 
 11  
 12 
 13 #define times 10
 14 
 15 #define N 501
 16 
 17 using namespace std;
 18 
 19 typedef unsigned long long LL;
 20 
 21 const LL INF=(LL)1<<61;
 22 
 23 LL key,ct,cnt,gd,lm,resa,resb,mini;
 24 
 25 LL fac[N],num[N];
 26 
 27  
 28 
 29 LL gcd(LL a,LL b)
 30 
 31 {
 32 
 33     return b?gcd(b,a%b):a;
 34 
 35 }
 36 
 37  
 38 
 39 LL multi(LL a,LL b,LL m)
 40 
 41 {
 42 
 43     LL ans=0;
 44 
 45     a%=m;
 46 
 47     while(b)
 48 
 49     {
 50 
 51         if(b&1)
 52 
 53         {
 54 
 55             ans=(ans+a)%m;
 56 
 57             b--;
 58 
 59         }
 60 
 61         b>>=1;
 62 
 63         a=(a+a)%m;
 64 
 65     }
 66 
 67     return ans;
 68 
 69 }
 70 
 71  
 72 
 73 LL quick_mod(LL a,LL b,LL m)
 74 
 75 {
 76 
 77     LL ans=1;
 78 
 79     a%=m;
 80 
 81     while(b)
 82 
 83     {
 84 
 85         if(b&1)
 86 
 87         {
 88 
 89             ans=multi(ans,a,m);
 90 
 91             b--;
 92 
 93         }
 94 
 95         b>>=1;
 96 
 97         a=multi(a,a,m);
 98 
 99     }
100 
101     return ans;
102 
103 }
104 
105  
106 
107 bool Miller_Rabin(LL n)
108 
109 {
110 
111     if(n==2) return true;
112 
113     if(n<2||!(n&1)) return false;
114 
115     LL m=n-1;
116 
117     int k=0;
118 
119     while(!(m&1))
120 
121     {
122 
123         k++;
124 
125         m>>=1;
126 
127     }
128 
129     for(int i=0;i<times;i++)
130 
131     {
132 
133         LL a=rand()%(n-1)+1;
134 
135         LL x=quick_mod(a,m,n);
136 
137         LL y=0;
138 
139         for(int j=0;j<k;j++)
140 
141         {
142 
143             y=multi(x,x,n);
144 
145             if(y==1&&x!=1&&x!=n-1) return false;
146 
147             x=y;
148 
149         }
150 
151         if(y!=1) return false;
152 
153     }
154 
155     return true;
156 
157 }
158 
159  
160 
161 LL Pollard_rho(LL n,LL c)
162 
163 {
164 
165     LL i=1,k=2;
166 
167     LL x=rand()%(n-1)+1;
168 
169     LL y=x;
170 
171     while(true)
172 
173     {
174 
175         i++;
176 
177         x=(multi(x,x,n)+c)%n;
178 
179         LL d=gcd((y-x+n)%n,n);
180 
181         if(1<d&&d<n) return d;
182 
183         if(y==x) return n;
184 
185         if(i==k)
186 
187         {
188 
189             y=x;
190 
191             k<<=1;
192 
193         }
194 
195     }
196 
197 }
198 
199  
200 
201 void Find(LL n,LL c)
202 
203 {
204 
205     if(n==1) return ;
206 
207     if(Miller_Rabin(n))
208 
209     {
210 
211         fac[ct++]=n;
212 
213         return ;
214 
215     }
216 
217     LL p=n;
218 
219     LL k=c;
220 
221     while(p>=n) p=Pollard_rho(p,c--);
222 
223     Find(p,k);
224 
225     The Find (n-/ P, K);
 226  
227  }
 228  
229   
230  
231  void DFS (Dept LL, LL Product)
 232  
233 { // Dept recursive depth, product which is a factor of 
234  
235      IF (Dept == CNT)
 236  
237      {
 238  
239          LL A = Product;
 240  
241          LL Key = B / A;
 242  
243          IF (GCD (A, B) == . 1 )
 244  
245          {
 246  
247              A * = Gd;
 248 
249             b*=gd;
250 
251             if(a+b<mini)
252 
253             {
254 
255                 mini=a+b;
256 
257                 resa=a;
258 
259                 resb=b;
260 
261             }
262 
263         }
264 
265         return ;
266 
267     }
268 
269     for(int i=0;i<=num[dept];i++)
270 
271     {
272 
273         if(product>mini) return ;
274 
275         dfs(dept+1,product);
276 
277         product*=fac[dept];
278 
279     }
280 
281 }
282 
283  
284 
285  
286 
287 void Solve(LL n)
288 
289 {
290 
291     ct=0;
292 
293     Find(n,120);
294 
295     sort(fac,fac+ct);
296 
297     num[0]=1;
298 
299     int k=1;
300 
301     for(int i=1;i<ct;i++)
302 
303     {
304 
305         if(fac[i]==fac[i-1])
306 
307             num[k-1]++;
308 
309         else
310 
311         {
312 
313             num[k]=1;
314 
315             fac[k++]=fac[i];
316 
317         }
318 
319     }
320 
321     cnt=k;
322 
323     dfs(0,1);
324 
325     if(resa>resb) swap(resa,resb);
326 
327 }
328 
329  
330 
331 int main()
332 
333 {
334 
335     while(cin>>gd>>lm)
336 
337     {
338 
339         if(gd==lm)
340 
341         {
342 
343             printf("%llu %llu\n",gd,lm);
344 
345             continue;
346 
347         }
348 
349         mini=INF;
350 
351         key=lm/gd;
352 
353         Solve(key);
354 
355         printf("%llu %llu\n",resa,resb);
356 
357     }
358 
359     return 0;
360 
361 }
View Code

 

Guess you like

Origin www.cnblogs.com/kongbursi-2292702937/p/12667940.html