Description 给出一整数n,求phi Input 一个正整数n(nM=1e18) Output 输出phi(n) Sample Input 8 Sample Output 4 Solution 用Pollard-rho对n素因子分解即可 Code
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef long double ld; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=200001; map<ll,int>factor; map<ll,int>::iterator it; vector<int>prime; int is_prime[maxn]; void get_prime() { is_prime[0]=is_prime[1]=0; for(int i=2;i<maxn;i++)is_prime[i]=1; for(int i=2;i<maxn;i++) if(is_prime[i]) { prime.push_back(i); for(int j=2*i;j<maxn;j+=i)is_prime[j]=0; } } ll gcd(ll a,ll b) { if(a==0)return 1; if(b==0)return a; return gcd(b,a%b); } ll Mul(ll a,ll b,ll p) { return (a*b-(ll)(a/(ld)p*b+1e-3)*p+p)%p; } ll Pow(ll a,ll b,ll c) { a%=c; ll ans=1; while(b) { if(b&1)ans=Mul(ans,a,c); a=Mul(a,a,c); b>>=1; } return ans; } bool Miller_Rabin(ll n,int times) { if(n<2)return 0; if(n==2)return 1; if(!(n&1))return 0; ll q=n-1; int k=0; while(q%2==0)k++,q>>=1; for(int i=0;i<times;i++) { ll a=rand()%(n-1)+1; ll x=Pow(a,q,n); if(x==1)continue; bool found=0; for(int j=0;j<k;j++) { if(x==n-1) { found=1; break; } x=Mul(x,x,n); } if(found)continue; return 0; } return 1; } ll Pollard_rho(ll n,int c) { ll x=2,y=2,d=1; while(d==1) { x=Mul(x,x,n)+c; y=Mul(y,y,n)+c; y=Mul(y,y,n)+c; d=gcd(abs(x-y),n); } if(d==n)return Pollard_rho(n,c+1); return d; } bool Is_Prime(ll n) { if(n<maxn)return is_prime[n]; return Miller_Rabin(n,20); } void Find_Factor(ll n) { if(Is_Prime(n)) { factor[n]++; return ; } else { for(int i=0;i<prime.size();i++) while(n%prime[i]==0) factor[prime[i]]++,n/=prime[i]; if(n!=1) { if(Is_Prime(n))factor[n]++; else { ll d=Pollard_rho(n,1); Find_Factor(d),Find_Factor(n/d); } } } } int main() { ll n; scanf("%lld",&n); get_prime(); factor.clear(); Find_Factor(n); ll ans=n; for(it=factor.begin();it!=factor.end();it++) ans=ans/(it->first)*(it->first-1); printf("%lld\n",ans); return 0; }