欧拉函数的介绍(附加欧拉定理和费马小定理的介绍)

欧拉函数是一个好东西.

欧拉函数的符号为φ,其中φ(n)表示1~n中与n互质的数的个数.

那么φ(n)的求法如下:

φ(n)=N*(p1-1)/p1*(p2-1)/p2*...*(pm-1)/pm.

其中p1,p2,...,pn什么的是唯一分解定理中n=p1^c1*p2^c2*p3^c3...*pm^cm.

若p是N的因子,就会筛掉n/p个数,同时q也会筛掉n/q个数,但它们中间的那部分n/(p*q)得加回来.

也就是我们可以推导出:N-n/p-n/q+n/(p*q)=N*(1-1/p)*(1-1/q).

那么代码实现如下:

int phi(int n){
  int ans=n;
  for (int i=1;i<=sqrt(n);i++)
    if (n%i==0){
      ans=ans/i*(i-1);
      while (n%i==0) n/=i;
    }
  if (n>1) ans=ans/n*(n-1);
  return ans;
}

那么这是一种O(sqrt(n))的算法.

当然它还可以在线性的时间里推出phi(1~n).

这就要利用到线性筛了.

线性筛blog地址:https://blog.csdn.net/hzk_cpp/article/details/80418319.

首先我们介绍几个欧拉函数的性质才能用线性筛求:

1.若n为素数,则φ(n)=n-1.

2.φ(a*b)=φ(a)*φ(b).

3.当p为素数时,φ(p^k)=(p-1)*p^(k-1).

证明:

首先比令n=p^k,那么比n小的正整数有p^k-1个.

容易得出其中与n不互素的数共有p^(k-1)-1个.

所以φ(p^k)=(p^k-1)-(p^(k-1)-1)=p^k-p^(k-1)=(p-1)*p^(k-1).

4.当p为素数时,若i%p=0,则φ(i*p)=p*φ(i).

5.当p为素数时,若i%p≠0,则φ(i*p)=(p-1)*φ(i).

那么用线性筛的思想,代码就很好写了:

const int N=10000000;
int pr[N+1],top=0,phi[N+1];
bool b[N+1];
void prime(int n){
  top=0;
  memset(b,1,sizeof(b));
  b[0]=0;b[1]=0;
  phi[0]=0;phi[1]=0;
  for (int i=2;i<=n;i++){
    if (b[i]) pr[++top]=i,phi[i]=i-1;
      for (int j=1;j<=top&&pr[j]*i<=n;j++){
        b[pr[j]*i]=0;
        if (i%pr[j]==0) {
          phi[i*pr[j]]=phi[i]*pr[j];
	    break;
        }else phi[i*pr[j]]=phi[i]*(pr[j]-1);
      } 
  }
}

再来一个定理叫做欧拉定理.

若a,p互质,则a^φ(p)≡1(mod p).

那么证明可以这样:

我们可以证明,集合{a1,a2,a3,...,aφ(p)}与{a*a1,a*a2,...,a*aφ(p)}在mod p意义下是同一个集合.

那么也就是说a^φ(p)*a1*a2*...*aφ(p)≡a1*a2*...*aφ(p)(mod p).

即a^φ(p)≡1(mod p).

证明过程很简洁吧.

其实是我太懒了,两个集合为什么相同未证.

那么这个定理还有一个推论:若a,n互质,则对于任意正整数b有a^b≡a^(b mod φ(n)) (mod n).

证明就是:设b=q*φ(n)+r,那么a^b≡a^(q*φ(n)+r)≡(a^φ(n))^q*a^r≡1*a^r≡a^(b mod φ(n)) (mod n).

接下来还有一个费马小定理:若p为素数,则a^p≡a  (mod p).

用欧拉定理就可以证明.

至于这些东西有什么用,我也很想知道.

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/80418130
今日推荐