原题
题目分析
这道题用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