GCD & 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 <cstdio>
  2 #include <cstdlib>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <utility>
  6 #include <ctime>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <string>
 10 #include <stack>
 11 #include <queue>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15
 16 using namespace std;
 17 typedef unsigned long long ULL;
 18 typedef long long LL;
 19 typedef long double LB;
 20 const int INF_INT=0x3f3f3f3f;
 21 const LL INF_LL=0x3f3f3f3f3f3f3f3f;
 22
 23 LL g,l;
 24 map<LL,int> prime_factor;//分别表示质因子 幂
 25
 26 LL Abs(LL x)
 27 {
 28     if(x<0) return x*=-1;
 29     return x;
 30 }
 31
 32 LL gcd(LL a,LL b)
 33 {
 34     return b?gcd(b,a%b):a;
 35 }
 36
 37 LL q_muti(LL a,LL b,LL p)
 38 {
 39     LL res=0;
 40     a%=p;
 41     while(b)
 42     {
 43         if(b&1) res=(res+a)%p;
 44         a=(a<<1)%p;
 45         b>>=1;
 46     }
 47     return res;
 48 }
 49
 50 LL q_power(LL a,LL b,LL p)
 51 {
 52     LL res=1;
 53     a%=p;
 54     while(b)
 55     {
 56         if(b&1) res=q_muti(res,a,p);
 57         a=q_muti(a,a,p);
 58         b>>=1;
 59     }
 60     return res;
 61 }
 62
 63 bool m_l(LL x,LL a)
 64 {
 65     if(q_power(a,x-1,x)!=1) return false;
 66     LL q=x-1;
 67     while(!(q&1))
 68     {
 69         q>>=1;
 70         LL t=q_power(a,q,x);
 71         if(t==1) continue;
 72         if(t==x-1) break;
 73         return false;
 74     }
 75     return true;
 76 }
 77
 78 bool is_prime(LL x)
 79 {
 80     if(x==0||x==1) return false;
 81     if(x==2||x==3) return true;
 82     else
 83     {
 84
 85         int k=10;
 86         for(int i=0;i<k;i++)
 87         {
 88             LL a=rand()%(x-3)+2;
 89             if(!m_l(x,a)) return false;
 90         }
 91         return true;
 92     }
 93 }
 94
 95 LL p_rho(LL n)
 96 {
 97     while(1) //一定找到一个因子
 98     {
 99         LL x=rand()%n,y=x,c=rand()%n,z=1;
100         int i=0,j=1;
101         while(++i)
102         {
103             x=(q_muti(x,x,n)+c)%n;
104             z=q_muti(z,Abs(y-x),n);
105             if(x==y||!z) break;
106             if(!(i%127)||i==j)
107             {
108                 LL g=gcd(z,n);
109                 if(g>1) return g;
110                 if(i==j) y=x,j<<=1;
111             }
112         }
113     }
114 }
115 /*这里给出两种分解质因子的方法
116 LL f(LL n)
117 {
118     if(is_prime(n)) return n;
119     return f(p_rho(n));
120 }
121
122 void factorize(LL n)
123 {
124     while(n!=1)
125     {
126         LL p=f(n);
127         while(!(n%p)) prime_factor[p]++,n/=p;
128     }
129 }
130 */
131
132 void factorize(LL n)
133 {
134     if(n==1) return ;
135     if(is_prime(n))
136     {
137         prime_factor[n]++;
138         return ;
139     }
140     LL p=p_rho(n);
141     factorize(p),factorize(n/p);
142 }
143
144 void dfs(LL num[],LL sum,int n,LL &maxn,LL &a,LL &b,int k,int now,int u,LL res)
145 {
146     if(u==k)
147     {
148         if(res+sum/res<maxn) maxn=res+sum/res,a=res,b=sum/res;
149         return ;
150     }
151     for(int i=now+1;i<n;i++) dfs(num,sum,n,maxn,a,b,k,i,u+1,res*num[i]);
152 }
153
154 void solve()
155 {
156     LL n=l/g;
157     prime_factor.clear();
158     factorize(n);
159     LL num[100];
160     int k=0;
161     for (map<LL,int>::iterator it=prime_factor.begin();it!=prime_factor.end();it++)
162     {
163         num[k]=1;
164         while (it->second) num[k]*=it->first,it->second--;
165         k++;
166     }
167     LL maxn=INF_LL,a,b;
168     for(int i=0;i<=k/2;i++) dfs(num,n,k,maxn,a,b,i,-1,0,1);
169     if(a>b) swap(a,b);
170     printf("%lld %lld\n",a*g,b*g);
171 }
172
173 int main()
174 {
175 //    freopen("std.in","r",stdin);
176 //    freopen("std.out","w",stdout);
177     srand(time(0)); //随机数生成
178     while(~scanf("%lld %lld",&g,&l)) solve();
179     return 0;
180 }

原文地址:https://www.cnblogs.com/VBEL/p/11437932.html

时间: 2024-10-19 16:48:28

GCD & LCM Inverse POJ 2429(Pollard Rho质因数分解)的相关文章

POJ 2429 long long 质因数分解

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16206   Accepted: 3008 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

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(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

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 (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

poj2429 GCD &amp; 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;