BZOJ4802:欧拉函数(Pollard-Rho,欧拉函数)
Description
已知N,求phi(N)
Input
正整数N。N<=10^18
Output
输出phi(N)
Sample Input
8
Sample Output
4
Solution
一开始读错题了……以为是求约束个数和……
读对题之后然后发现我不会就问旁边的宽嫂……
宽嫂:这不是欧拉函数的定义式么?我初中就会了啊。
我:
然后去百度了一发,发现一个数的欧拉函数就是
$\prod (p_i-1)*p_i^{k_i-1}$,其中$p_i$是这个数的质因子,$k_i$是这个质因子的次数……
然后套板子就行了。
发现我之前抄了个假的快速乘然后还花了我一会儿改代码+改博客……QAQ
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<map> 5 #include<algorithm> 6 #define LL long long 7 using namespace std; 8 9 LL n,ans=1,Num[109],cnt; 10 LL prime[15]={2,3,5,7,11,13,17,19,23,29,31}; 11 map<LL,LL>Keg; 12 13 LL Mul(LL a,LL b,LL MOD) 14 { 15 LL tmp=a*b-(LL)((long double)a*b/MOD+0.1)*MOD; 16 return tmp<0?tmp+MOD:tmp; 17 } 18 19 LL Qpow(LL a,LL b,LL MOD) 20 { 21 LL ans=1; 22 while (b) 23 { 24 if (b&1) ans=Mul(ans,a,MOD); 25 a=Mul(a,a,MOD); b>>=1; 26 } 27 return ans; 28 } 29 30 LL gcd(LL a,LL b) {return b==0?a:gcd(b,a%b);} 31 32 bool Miller_Rabin(LL n) 33 { 34 if (n==2) return 1; 35 if (n<2 || n%2==0) return 0; 36 LL m=n-1,l=0; 37 while (m%2==0) m>>=1, l++; 38 for (int i=0; i<11; ++i) 39 { 40 LL p=prime[i],w=Qpow(p,m,n); 41 if (w==n-1 || w==1 || p==n) continue; 42 for (int j=1; j<=l; ++j) 43 { 44 LL u=Mul(w,w,n); 45 if (u==1 && w!=n-1 && w!=1) return 0; 46 w=u; 47 } 48 if (w!=1) return 0; 49 } 50 return 1; 51 } 52 53 LL Pollard_Rho(LL n,LL c) 54 { 55 LL x=(rand()+1)%n,y=x,p=1,k=2; 56 for (LL i=1; p==1; ++i) 57 { 58 x=(Mul(x,x,n)+c)%n; 59 p=x>y?x-y:y-x; 60 p=gcd(p,n); 61 if (i==k) y=x, k=k+k; 62 } 63 return p; 64 } 65 66 void Solve(LL n) 67 { 68 if (n==1) return; 69 if (Miller_Rabin(n)) 70 { 71 if (!Keg[n]) Num[++cnt]=n; 72 ++Keg[n]; return; 73 } 74 LL t=n; 75 while (t==n) t=Pollard_Rho(n,rand()%(n-1)+1); 76 Solve(t); Solve(n/t); 77 } 78 79 int main() 80 { 81 scanf("%lld",&n); 82 Solve(n); 83 for (int i=1; i<=cnt; ++i) 84 ans=ans*(Num[i]-1)*Qpow(Num[i],Keg[Num[i]]-1,2e18); 85 printf("%lld\n",ans); 86 }