思路:
因为当n>=1e10的时候,线性筛就不好使啦。所以要用一个公式
φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn)
证明详见:《公式证明:欧拉函数》
Miller-Rabin算法:
判断某个数是否是素数,不是素数则返回一个因子。
Pollard-Rho算法:
利用Miller-Rabin求出 质因数。
具体的:
如果当前的数不是质数,找质因数 再搜Rho(n/d)和Rho(d)
如果是质数(不一定准确),再去判断。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<set> 5 #include<vector> 6 #include<map> 7 #include<string> 8 #include<iomanip> 9 #include<iostream> 10 #include<cmath> 11 #include<queue> 12 using namespace std; 13 #define ALL(x,S) for(x=S.begin();x!=S.end();x++) 14 typedef long long LL; 15 typedef long double real; 16 bool pd_prime[10010]; 17 set<LL> S; 18 set<LL>::iterator pos; 19 LL n; 20 void prepare() 21 { 22 int i,j; 23 memset(pd_prime,1,sizeof pd_prime); 24 pd_prime[1]=0; 25 for(int i=2;i<=10000;i++) 26 if(pd_prime[i]) 27 for(int j=2;j<=10000/i;j++) 28 pd_prime[i*j]=0; 29 } 30 void addp(LL t) 31 { S.insert(t);} 32 LL gcd(LL a,LL b) 33 { 34 if(!b) return a; 35 return gcd(b,a%b); 36 } 37 LL mul(LL a,LL b,LL mod) 38 { 39 LL ans=0; 40 while(b) 41 { 42 if(b&1) ans=(ans+a)%mod; 43 a=(a+a)%mod; 44 b>>=1; 45 } 46 return ans; 47 } 48 LL pow(LL a,LL b,LL mod) 49 { 50 LL ans=1; 51 while(b) 52 { 53 if(b&1) ans=mul(ans,a,mod); 54 b>>=1; 55 a=mul(a,a,mod); 56 } 57 return ans; 58 } 59 bool MR(LL n,LL k) 60 { 61 LL s=n-1,w=0; 62 while(!(s&1)) 63 w++,s>>=1; 64 LL y=pow(k,s,n); 65 if(y==1 || y==n-1) 66 return 1; 67 while(w--) 68 { 69 y=mul(y,y,n); 70 if(y==n-1) 71 return 1; 72 } 73 return 0; 74 } 75 bool prime(LL n) 76 { 77 if(n<=10000) 78 return pd_prime[n]; 79 bool flag=1; 80 for(int i=1;i<=50;i++) 81 if(pd_prime[i]) 82 if(!MR(n,i)) flag=0; 83 return flag; 84 } 85 void rho(LL n) 86 { 87 if(n==1) return ; 88 if(n==4) 89 { 90 addp(2); 91 addp(2); 92 return ; 93 } 94 if(prime(n)) 95 { 96 addp(n); 97 return ; 98 } 99 LL x,y,d,p; 100 while(1) 101 { 102 x=2,y=2,d=1; 103 p=mul(rand(),rand(),100000000); 104 if(d==1) 105 { 106 x=(mul(x,x,n)+p)%n; 107 y=(mul(y,y,n)+p)%n; 108 y=(mul(y,y,n)+p)%n; 109 d=gcd(abs(x-y),n); 110 } 111 if(d==n) continue; 112 rho(d);rho(n/d); 113 return ; 114 } 115 } 116 LL phi(LL x) 117 { 118 S.clear(); 119 rho(x); 120 LL ans=x; 121 ALL(pos,S) 122 ans=ans/(*pos)*((*pos)-1); 123 return ans; 124 } 125 int main() 126 { 127 freopen("phi.in","r",stdin); 128 freopen("phi.out","w",stdout); 129 prepare(); 130 scanf("%lld",&n); 131 cout<<phi(n); 132 return 0; 133 }