【POJ2429】GCD & LCM Inverse-Pollard-rho分解+枚举
测试地址:GCD & LCM Inverse
题目大意:给定
做法:这个题目应该使用Pollard-rho分解算法+枚举(或者有其他的方法?不管啦)。
我们来分析一下满足条件的
由于已经除掉了
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll unsigned long long
using namespace std;
ll GCD,LCM,p[11]={2,3,5,7,11,13,17,19,23,29};
ll fac[110]={0},A,B,mins;
int tot;
ll mult(ll a,ll b,ll mod)
{
ll s=a,sum=0;
while(b)
{
if (b&1)
{
sum+=s;
if (sum>=mod) sum-=mod;
}
b>>=1;
s<<=1;
if (s>=mod) s-=mod;
}
return sum;
}
ll power(ll a,ll b,ll mod)
{
ll s=a,sum=1;
while(b)
{
if (b&1) sum=mult(sum,s,mod);
b>>=1;s=mult(s,s,mod);
}
return sum;
}
bool witness(ll n,ll a)
{
ll p=power(a,n-1,n);
if (p!=1) return 0;
else
{
ll s=n-1;
while(!(s%2)&&p==1)
{
s>>=1;
p=power(a,s,n);
}
if (p==1||p==n-1) return 1;
else return 0;
}
}
bool miller_rabin(ll n)
{
if (n<=29)
{
for(int i=0;i<=9;i++)
if (p[i]==n) return 1;
return 0;
}
for(int i=0;i<=9;i++)
if (!witness(n,p[i])) return 0;
return 1;
}
ll gcd(ll a,ll b)
{
return (b==0)?a:gcd(b,a%b);
}
ll pollard_rho(ll n,ll c)
{
ll x=rand()%n,y=x,d,i=1,k=2;
while(1)
{
i++;
x=(mult(x,x,n)+c)%n;
d=gcd(n+y-x,n);
if (d>1&&d<n) return d;
if (y==x) return n;
if (i==k) y=x,k<<=1;
}
}
void find_factor(ll n)
{
if (n==1) return;
if (miller_rabin(n))
{
fac[++tot]=n;
return;
}
ll p=n;
while(p>=n) p=pollard_rho(p,rand()%(n-1)+1);
find_factor(p);
find_factor(n/p);
}
bool cmp(ll a,ll b) {return a<b;}
void work()
{
int d=0;
sort(fac+1,fac+tot+1,cmp);
for(int i=1;i<=tot;i++)
{
if (fac[i]!=fac[i-1])
{
d++;
if (i!=d) fac[d]=1;
}
if (i!=d) fac[d]*=fac[i];
}
tot=d;
for(int i=0;i<(1<<tot);i++)
{
ll nowa=1,nowb=1,k=i;
for(int j=1;j<=tot;j++)
{
if (k&1) nowb*=fac[j];
else nowa*=fac[j];
k>>=1;
}
if ((nowa+nowb)*GCD<mins) A=nowa*GCD,B=nowb*GCD,mins=(nowa+nowb)*GCD;
}
}
int main()
{
while(scanf("%lld%lld",&GCD,&LCM)!=EOF)
{
tot=0;A=B=1;mins=0;
for(int i=0;i<=63;i++) mins+=1<<i;
find_factor(LCM/GCD);
work();
if (A>B) {ll t=A;A=B;B=t;}
printf("%lld %lld\n",A,B);
}
return 0;
}