解题思路:
直接把n用Rabin-Miller+pollard_rho算法质因数分解(不会的可以看这里),用欧拉函数的计算式计算即可。
注意pollard_rho算法会把n完全质因数分解,所以最后要去重。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll yz[100000];
int m;
ll ksc(ll x,ll y,ll p)
{
ll res=0;
for(;y;y>>=1,x=(x+x)%p)
if(y&1)res=(res+x)%p;
return res;
}
ll ksm(ll x,ll y,ll p)
{
ll res=1;
for(;y;y>>=1,x=ksc(x,x,p))
if(y&1)res=ksc(res,x,p);
return res;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
bool check(ll a,ll n,ll r,ll s)
{
ll x=ksm(a,r,n),pre=x;
for(int i=1;i<=s;i++)
{
x=ksc(x,x,n);
if(x==1&&pre!=1&&pre!=n-1)return 1;
pre=x;
}
if(x!=1)return 1;
return 0;
}
bool MR(ll n)
{
if(n<2)return 0;
if(n==2)return 1;
if(n%2==0)return 0;
ll r=n-1,s=0;
while(!(r&1))r>>=1,s++;
for(int i=0;i<9;i++)
if(check(rand()%(n-1)+1,n,r,s))
return 0;
return 1;
}
ll rho(ll n,ll c)
{
ll k=2,x=rand()%n,y=x,p=1;
for(ll i=1;p==1;i++)
{
x=(ksc(x,x,n)+c)%n;
p=y>x?y-x:x-y;
p=gcd(n,p);
if(i==k)y=x,k<<=1;
}
return p;
}
void solve(ll n)
{
if(n==1)return;
if(MR(n))
{
yz[++m]=n;
return;
}
ll t=n;
while(t==n)t=rho(n,rand()%(n-1)+1);
solve(t),solve(n/t);
}
int main()
{
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
srand(1);
ll n;cin>>n;
solve(n);
sort(yz+1,yz+m+1);
m=unique(yz+1,yz+m+1)-yz-1;
for(int i=1;i<=m;i++)n=n/yz[i]*(yz[i]-1);
cout<<n;
return 0;
}