zoukankan      html  css  js  c++  java
  • 数论五·欧拉函数

    描述

    小Hi和小Ho有时候会用密码写信来互相联系,他们用了一个很大的数当做密钥。小Hi和小Ho约定了一个区间[L,R],每次小Hi和小Ho会选择其中的一个数作为密钥。

    小Hi:小Ho,这次我们选[L,R]中的一个数K。

    小Ho:恩,小Hi,这个K是多少啊?

    小Hi:这个K嘛,不如这一次小Ho你自己想办法算一算怎么样?我这次选择的K满足这样一个条件:

    假设φ(n)表示1..n-1中与n互质的数的个数。对于[L,R]中的任意一个除K以外的整数y,满足φ(K)≤φ(y)且φ(K)=φ(y)时,K<y。

    也即是K是[L,R]中φ(n)最小并且值也最小的数。

    小Ho:噫,要我自己算么?

    小Hi:没错!

    小Ho:好吧,让我想一想啊。

    <几分钟之后...>

    小Ho:啊,不行了。。感觉好难算啊。

    小Hi:没有那么难吧,小Ho你是怎么算的?

    小Ho:我从枚举每一个L,R的数i,然后利用辗转相除法去计算[1,i]中和i互质的数的个数。但每计算一个数都要花好长的时间。

    小Hi:你这样做的话,时间复杂度就很高了。不妨告诉你一个巧妙的算法吧:

    提示:欧拉函数

    输入

    第1行:2个正整数, L,R,2≤L≤R≤5,000,000。

    输出

    第1行:1个整数,表示满足要求的数字K

    样例输入
    4 6
    样例输出
    4
    思路{
      1) 若n为素数,则φ(n) = n - 1

    显然,由于n为素数,1~n-1与n都只有公因子1,因此φ(n) = n - 1。

    (2) 若n = p^k,p为素数(即n为单个素数的整数幂),则φ(n) = (p-1)*p^(k-1)

    因为n是p的整数幂,因此所有p的倍数和n都不互质。小于n的p的倍数一共有p^(k-1)-1个,因此和n互质的个数为:

    p^k-1 - (p^(k-1)-1) = p^k - p^(k-1) = (p-1)*p^(k-1)

    (3) 若p和q互质,则φ(p*q) = φ(p) * φ(q)

      对于所有小于pq的整数u,可以表示为u=aq+r。(a=0,1,2,...,p-1,r=0,1,...,q-1)。

      对于u = aq + r, 设R = u mod p,0≤R<q。对于一个固定的r,设a1, a2满足0 <= a1, a2 < p且a1≠a2,有:

      u1 = a1*q+r, u2 = a2*q+r
      u1-u2=(a1-a2)*q

      因为p与q互质,且|a1-a2|<p,则|u1-u2|一定不是p的倍数。

      所以对于每一个固定的r,其对应的p个u = a*q+r(a=0,1,2,...,p-1)对mod p来说余数都不相同,即u mod p的结果恰好取遍0,1,...,p-1中的每一个数。

      下面证明一个引理:u mod p与p互质 <=> u与p互质,其证明如下:

      假设a,b互质,c = a mod b。
      假设c与b不互质,则存在d≥1,使得c=nd, b=md。
      由于c = a mod b,因此a = kb + c,
      则a = kmd + nd = (kn+m)d
      因此d是a,b的公因数,与a,b互质矛盾。
      假设不成立,所以c与b互质。

      因此对于任意一个确定的r,与其对应的p个u中恰好有φ(p)个与p互质。

      同理,由u = aq + r知r与q互质 <=> u与q互质。因此在0..q-1中恰好有φ(q)个r使得u与q互质。

      综上,当r与q互质的情况下,固定r可以得到φ(p)个与p和q都互质的数。

      满足条件的r一共用φ(q)个,所以一共能找到有φ(p) * φ(q)个与p和q都互质的数。

      由此得证:φ(p*q) = φ(p) * φ(q)

      若p为质数,n为任意整数:

      (1) 若p为n的约数,则φ(n*p) = φ(n) * p

      若p为n的约数,且p为质数。则我们可以将n表示为p^k*m。m表示其他和p不同的质数的乘积。

      显然有p^k与m互质,则:

      φ(n) = φ(p^k)*φ(m) = (p-1)*p^(k-1)*φ(m)
      φ(n*p) = φ(p^(k+1))*φ(m) = (p-1)*p^k*φ(m) = (p-1)*p^(k-1)*φ(m) * p =  φ(n) * p

      (2) 若p为不为n的约数,则φ(n*p) = φ(n) * (p-1)

      由p不为n的约数,因此p与n互质,所以φ(n*p) = φ(n) * φ(p) = φ(n)*(p-1)

      根据这两条定理,当我们得到一个n时,可以枚举质数p来递推的求解φ(n*p)。这一步是不是觉得很眼熟呢?

      只需要在欧拉筛代码的基础上做一个小改动,就可以得到递推求解φ(n)的算法

    }
     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<queue>
     7 #include<ctime>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 #define MAXX 5000001
    12 using namespace std;
    13 int minnum;
    14 int in[MAXX],ans,r,l,phi[MAXX];
    15 bool ha[MAXX];
    16 int main(){
    17   scanf("%d%d",&l,&r);phi[0]=MAXX;
    18   for(int i=2;i<=r;++i){
    19     if(!ha[i]){
    20       in[++ans]=i;
    21       phi[i]=i-1;
    22     }
    23     for(int j=1;j<=ans;++j){
    24       if(in[j]*i>r)break;
    25       if(!(i%in[j])){//yinzi
    26     ha[i*in[j]]=true;
    27     phi[i*in[j]]=phi[i]*in[j];
    28     break;
    29       }else phi[i*in[j]]=phi[i]*(in[j]-1),ha[i*in[j]]=true;
    30     }
    31    }
    32   for(int i=l;i<=r;++i)if(phi[minnum]>phi[i])minnum=i;
    33   printf("%d",minnum);
    34   return 0;
    35 }
    
    
  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    《EffectiveJava中文第二版》 高清PDF下载
    《MoreEffectiveC++中文版》 pdf 下载
    《啊哈c语言》 高清 PDF 下载
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6639467.html
Copyright © 2011-2022 走看看