POJ2429 GCD & LCM Inverse pollard_rho大整数分解

 

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

 

 

题意:给出两个数的最大公约数和最小公倍数,让你找出满足条件的两个数,使他们的和最小。

 

题解:

对于两个数a,b和他们的最大公约数gcd以及最小公倍数lcm,有lcm=a*b/gcd,进一步变形可以得到:(a/gcd * b/gcd)*gcd=lcm,即(a/gcd * b/gcd)=lcm/gcd,我们令m=a/gcd,n=b/gcd,那么问题就变为了:找出两个互素的整数,使他们的乘积为key=lcm/gcd。我们可以用Pollard_rho算法进行质因素分解的方法找出lcm/gcd的所有素因子,然后dfs找出任意几个素数因子之积(设为x),设y=key/x,找出最小的x+y就行了

 

代码:

  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     Find(n/p,k);
226 
227 }
228 
229  
230 
231 void dfs(LL dept,LL product)
232 
233 {//dept为递归深度,product为其中一个因子
234 
235     if(dept==cnt)
236 
237     {
238 
239         LL a=product;
240 
241         LL b=key/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

 

posted @ 2020-04-09 16:49  kongbursi  阅读(255)  评论(0编辑  收藏  举报