BZOJ-4802 欧拉函数(Pollard-Rho算法模板)
题目描述
给出 \(n(1\leq n\leq 10^{18})\),求 \(\varphi(n)\)。
分析
根据 \(\varphi(n)=n\times \displaystyle\prod\limits_{i=1}^{k}(1-\frac{1}{p_i})\),\(\text{Pollard-Rho}\) 分解即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define int128 __int128
long long quick_pow(long long a,long long b,long long mod)
{
long long ans=1;
while(b)
{
if(b&1)
ans=(int128)ans*a%mod;
a=(int128)a*a%mod;
b>>=1;
}
return ans;
}
long long max_factor,n;
bool Miller_Rabin(long long p)
{
if(p<2)
return 0;
if(p==2)
return 1;
if(p==3)
return 1;
long long d=p-1,r=0;
while(d%2==0)
{
r++;
d>>=1;
}
for(long long k=0;k<10;k++)
{
long long a=rand()%(p-2)+2;
long long x=quick_pow(a,d,p);
if(x==1||x==p-1)
continue;
for(int i=0;i<r-1;i++)
{
x=(int128)x*x%p;
if(x==p-1)
break;
}
if(x!=p-1)
return 0;
}
return 1;
}
long long f(long long x,long long c,long long n)
{
return ((int128)x*x+c)%n;
}
long long Pollard_Rho(long long n)
{
long long s=0,t=0;
long long c=rand()%(n-1)+1;
int step=0,goal=1;
long long val=1;
for(goal=1; ;goal<<=1,s=t,val=1)
{
for(step=1;step<=goal;step++)
{
t=f(t,c,n);
val=(int128)val*abs(t-s)%n;
if(step%127==0)
{
long long d=__gcd(val,n);
if(d>1)
return d;
}
}
long long d=__gcd(val,n);
if(d>1)
return d;
}
}
long long factor[300010];
int cnt;
void fac(long long x)
{
if(x<=max_factor||x<2)
return ;
if(Miller_Rabin(x))
{
factor[++cnt]=x;
//max_factor=max(max_factor,x);
return ;
}
long long p=x;
while(p>=x)
p=Pollard_Rho(x);
while(x%p==0)
x=x/p;
fac(x);fac(p);
}
int main()
{
int T=1;
//cin>>T;
while(T--)
{
srand((unsigned)time(NULL));
max_factor=0;
scanf("%lld",&n);
fac(n);
sort(factor+1,factor+1+cnt);
cnt=unique(factor+1,factor+1+cnt)-factor-1;
long long ans=n;
for(int i=1;i<=cnt;i++)
ans=ans/factor[i]*(factor[i]-1);
cout<<ans<<endl;
/*if(max_factor==n)
puts("Prime");
else
printf("%lld\n",max_factor);
*/
}
return 0;
}
posted on 2020-11-27 17:51 DestinHistoire 阅读(67) 评论(0) 编辑 收藏 举报