pollard_rho例题
\(pollard\_rho\) 例题
\(POJ 1811\)
题意:判断一个数是不是素数,如果是素数,输出 \(Prime\) 否则,输出最小的素因子。
题解:使用 \(Miller\_Rabin\) 法则筛选素数,之后使用 \(pollard\_rho\) 进行因子分解,找到最小值。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = 501;
const int TestCase = 10;
int cnt;
ll N;
ll minn,mina,minb;
ll prime[MAXN];
ll fac[MAXN];
ll num[MAXN];
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll random(ll n){
return (ll)((double)rand()/RAND_MAX*n+0.5);
}
ll multi(ll a,ll b,ll m){
ll ret=0;
while(b>0){
if(b&1)ret=(ret+a)%m;
b>>=1;
a=(a<<1)%m;
}
return ret;
}
ll pow(ll a,ll b,ll m){
ll ans=1;
a%=m;
while(b){
if(b&1)ans=multi(ans,a,m);
b>>=1;
a=multi(a,a,m);
}
return ans;
}
bool Witness(ll a,ll n){
ll m=n-1;
int j=0;
while(!(m&1)){
++j;m>>=1;
}
ll x=pow(a,m,n);
if(x==1||x==n-1)return false;
while(j--){
x=x*x%n;
if(x==n-1)return false;
}
return true;
}
bool miller_rabin(ll n){
if(n<2)return false;
if(n==2)return true;
if(!(n&1))return false;
for(int i=1;i<=TestCase;++i){
ll a=random(n-2)+1;
if(Witness(a,n))return false;
}
return true;
}
ll pollard_rho(ll n,int c){
ll x,y,d,i=1,k=2;
x=random(n-1)+1;
y=x;
while(true){
++i;
x=(multi(x,x,n)+c)%n;
d=gcd(y-x,n);
if(1<d&&d<n)return d;
if(x==y)return n;
if(i==k){
y=x;
k<<=1;
}
}
}
void find(ll n,int k){
if(n==1)return;
if(miller_rabin(n)){
// prime[++cnt]=n;
minn=min(minn,n);
return;
}
ll p=n;
while(p>=n)
p=pollard_rho(p,--k);
find(p,k);
find(n/p,k);
}
int main(){
ll T;
cin>>T;
while(T--){
ll N;
cin>>N;
if(miller_rabin(N))cout<<"Prime"<<endl;
else {
minn=N;
find(N,107);
cout<<minn<<endl;
}
}
return 0;
}
\(POJ 2429\)
题意:已知 \(gcd(a,b)\) 和 \(lcm(a,b)\) 求解 \(a\) , \(b\) 使得 \(a+b\) 最小
题解:使用 \(pollard\_rho\) 进行质数分解,之后使用 \(dfs\) 搜索即可。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = 501;
const int TestCase = 10;
int cnt;
ll N;
ll prime[MAXN];
ll fac[MAXN];
ll num[MAXN];
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll random(ll n){
return (ll)((double)rand()/RAND_MAX*n+0.5);
}
ll multi(ll a,ll b,ll m){
ll ret=0;
while(b>0){
if(b&1)ret=(ret+a)%m;
b>>=1;
a=(a<<1)%m;
}
return ret;
}
ll pow(ll a,ll b,ll m){
ll ans=1;
a%=m;
while(b){
if(b&1)ans=multi(ans,a,m);
b>>=1;
a=multi(a,a,m);
}
return ans;
}
bool Witness(ll a,ll n){
ll m=n-1;
int j=0;
while(!(m&1)){
++j;m>>=1;
}
ll x=pow(a,m,n);
if(x==1||x==n-1)return false;
while(j--){
x=x*x%n;
if(x==n-1)return false;
}
return true;
}
bool miller_rabin(ll n){
if(n<2)return false;
if(n==2)return true;
if(!(n&1))return false;
for(int i=1;i<=TestCase;++i){
ll a=random(n-2)+1;
if(Witness(a,n))return false;
}
return true;
}
ll pollard_rho(ll n,int c){
ll x,y,d,i=1,k=2;
x=random(n-1)+1;
y=x;
while(true){
++i;
x=(multi(x,x,n)+c)%n;
d=gcd(y-x,n);
if(1<d&&d<n)return d;
if(x==y)return n;
if(i==k){
y=x;
k<<=1;
}
}
}
void find(ll n,int k){
if(n==1)return;
if(miller_rabin(n)){
prime[++cnt]=n;
return;
}
ll p=n;
while(p>=n)
p=pollard_rho(p,--k);
find(p,k);
find(n/p,k);
}
ll minn,mina,minb;
int len=0;
void dfs(int id,ll tmp){
if(id==len+1){
if(N/tmp+tmp<minn){
mina=tmp;
minb=N/tmp;
minn=mina+minb;
}
return;
}
dfs(id+1,tmp);
tmp*=fac[id];
if(tmp>=minn)return;
dfs(id+1,tmp);
}
void slove(ll n,ll x){
cnt=0;
find(n,107);
sort(prime+1,prime+cnt+1);
len=0;
fac[len]=prime[1];
num[len]=1;
for(int i=2;i<=cnt;++i){
if(fac[len]==prime[i]){
++num[len];
}
else{
fac[++len]=prime[i];
num[len]=1;
}
}
for(int i=0;i<=len;++i){
ll tmp=1;
for(int j=0;j<num[i];++j){
tmp*=fac[i];
}
fac[i]=tmp;
}
// for(int i=0;i<=len;++i)
// cout<<num[i]<<" "<<fac[i]<<endl;
}
int main(){
ll x,y;
while(cin>>x>>y){
if(x==y)cout<<x<<" "<<y<<endl;
else {
N=y/x;
slove(N,x);
minn=N+1;
mina=1;minb=N;
dfs(0,1);
cout<<min(mina,minb)*x<<" "<<(mina+minb-min(mina,minb))*x<<endl;
}
}
return 0;
}
新赛季的开始