码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-08-31 10:42:49      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:queue   gcd   scanf   family   blank   ack   color   break   两种   

原题

题目链接

题目分析

这道题用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 }

 

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

标签:queue   gcd   scanf   family   blank   ack   color   break   两种   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!