求一个极大数的欧拉函数 phi(i)

思路:

  因为当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 } 
原文地址:https://www.cnblogs.com/CLGYPYJ/p/7635976.html