传送门

Pollard−rhoPollard-rhoPollard−rho模板题。

题意简述:求ϕ(n),n≤1e18\phi(n),n\le 1e18ϕ(n),n≤1e18

先把nnn用Pollard−rhoPollard-rhoPollard−rho分解质因数,然后就可以算了。

代码:

#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define ri register int
using namespace std;
typedef unsigned int uint;
typedef long long ll;
tr1::unordered_map<ll,int>S;
int pri[10]={2,3,5,7,11,13,17,19,23,29};
vector<ll>fac;
inline uint unit(){
    static uint state0=19491001;
    state0^=(state0>>13);
    state0^=(state0<<17);
    state0^=(state0>>5);
    return state0;
}
inline ll ksc(ll a,ll b,ll mod){return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;}
inline ll ksm(ll a,ll p,ll mod){ll ret=1;a%=mod;for(;p;p>>=1,a=ksc(a,a,mod))if(p&1)ret=ksc(ret,a,mod);return ret;}
inline bool check(ll x,ll a,ll s,ll t){
	a=ksm(a,t,x);
	ll p=a;
	if(a==1||a==x-1)return 1;
	while(s--){
		a=ksc(p,p,x);
		if(a==1&&(p!=x-1&&p!=1))return 0;
		p=a;
	}
	return p==1;
}
inline bool MRT(ll x){
	if(x==2||x==3)return fac.push_back(x),1;
	if(!(x&1))return 0;
	if(x%6!=1&&x%6!=5)return 0;
	ll s=0,t=x-1;
	while(!(t&1))t>>=1,++s;
	for(ri i=0;i<10;++i){
		if(x==pri[i])return fac.push_back(x),1;
		if(!(x%pri[i]))return 0;
		if(!check(x,pri[i],s,t))return 0;
	}
	return fac.push_back(x),1;
}
inline ll F(ll x,ll c,ll mod){return (ksc(x,x,mod)+c)%mod;}
inline ll gcd(ll a,ll b){while(b){ll t=a;a=b,b=t%a;}return a;}
inline ll rho(ll n,ll c){
	ll x=unit()%n+1,y=x,p=1;
	for(ri i=1,k=2;p==1;++i){
		x=F(x,c,n),p=gcd(y>x?y-x:x-y,n);
		if(i==k)y=x,k<<=1;
	}
	return p;
}
inline void solve(ll n){
	if(n==1||MRT(n))return;
	ll d=rho(n,unit()%n);
	while(d==n)d=rho(n,unit()%n);
	solve(n/d),solve(d);
}
int main(){
	freopen("lx.in","r",stdin);
	ll n,ans;
	scanf("%lld",&n),solve(n),ans=n;
	for(ri i=fac.size()-1;~i;--i){
		if(S[fac[i]])continue;
		S[fac[i]]=1,ans=ans/fac[i]*(fac[i]-1);
	}
	return cout<<ans,0;
}
05-07 15:27