欧拉函数

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

大家好,又见面了,我是你们的朋友全栈君。

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

解:用欧拉函数求解

  φ(n),一般被称为欧拉函数。其定义为:小于n的正整数中与n互质的数的个数。

  先了解四个性质:

  (1) u mod p 与 p 互质 <=> u 和 p 互质

设 a, b互质, c = a mod b

    假设 c 与 b 不互质,则存在着 d >= 1, 使得 c = nd, b = md (d 为b,c 的公约数)

    因为 c = a mod b, 所以 a = kb + c

    则 a = kmd + nd = (km + n)d

    因为 b = md,a = (km + n)d

    所以 a,b 不互质,与之前矛盾,假设不成立,所以 b 和 c 互质

    所以 a 和 b 互质 => b 和 a mod b 互质

    同理 可得 b 和 a mod b 互质 => a 和 b 互质

  (2) 若 n 是素数,则 φ(n) = n – 1

    这是显然的

  (3) 若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)

  (4) 若 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 互质

    因此对于任意一个确定的 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的约数,则φ(n*p) = φ(n) * p,

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

  根据这两条,当我们得到一个 n 时,可以枚举质数 p 来递推的求解φ(n*p)

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

isPrime[] = true
primeList = []
phi = []    // phi[n]表示n的欧拉函数
primeCount = 0
For i = 2 .. N
    If isPrime[i] Then
        primeCount = primeCount + 1
        primeList[ primeCount ] = i
        phi[i] = i - 1 // 质数的欧拉函数为p-1
    End If 
    For j = 1 .. primeCount
        If (i * primeList[j] > N) Then
            Break
        End If
        isPrime[ i * primeList[j] ] = false
        If (i % primeList[j] == 0) Then
            // primeList[j]是i的约数,φ(n*p) = φ(n) * p
            phi[ i * primeList[j] ] = phi[i] * primeList[j];
            Break
        Else 
            // primeList[j]不是i的约数,φ(n*p) = φ(n) * (p-1)
            phi[ i * primeList[j] ] = phi[i] * (primeList[j] - 1);
        End If
    End If
End For

上源代码

<span role="heading" aria-level="2">欧拉函数
<span role="heading" aria-level="2">欧拉函数

#include <iostream>
#include <cstring>
#include <algorithm>
#define N 5000010
using namespace std;
int ou[N];
int main(){
    int l,r,min=N-1;
    cin >> l >> r;
    for(int i=0;i<=r;i++){
        ou[i]=i;
    }
    //求欧拉函数 
    for(int i=2;i<=r;i++){
        if(ou[i]==i){
            for(int j=i;j<=r;j+=i){
                ou[j]=ou[j]/i*(i-1);
            }
        }
    }
    ou[min]=N;
    for(int i=l;i<=r;i++){
        min=ou[min]>ou[i]?i:min;
    }
    cout << min << endl;
    return 0;
}

View Code

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155244.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mt4历史数据回测_mt410年历史数据

    mt4历史数据回测_mt410年历史数据这个网站只能下载2001年-当前时间前一个月的数据,还是挺全的。但是下载下来之后好像是一分钟图的,妈蛋其实我想要1小时图的EURUSD历史数据。网站地址:http://www.fxfupan.com/datacenter.html它们网站上的复盘大师可以试下,回去我就试下看看他们的软件怎么样刚才找到一个更好的,上面的东西可以不必看了。福汇官方有个历史数据下载器软件(初阶免费),登录自己的福汇账号,…

    2022年8月15日
    6
  • 2023年北京理工大学理论力学考研上岸前辈备考经验指导

    2023年北京理工大学理论力学考研上岸前辈备考经验指导2021年我400分+考研成功上岸北京理工大学,回顾2020一年的辛苦蹒跚,觉得值得。一、考研择校及报考因素考量关于考研择校方面,我主要考虑到未来从事行业、地域、学校实力和名气这几个方面,排列顺序按照重要度先后。首先是最为关键的未来从事行业方面,考研之前其实就应该大体思考一下未来的发展方向,这相当于给自己以后好几年定一个基调。比如我本科是航空航天类,这个专业看似和其它工科脱节了,成了大国工酱,实际上万物可转航空航天方面,我去年拿到过北京航天科工某所的offer,基本上不管是工科什么专业都招的。航空航

    2022年6月13日
    28
  • arcgis二次开发python-ArcGIS 二次开发专题 序「建议收藏」

    arcgis二次开发python-ArcGIS 二次开发专题 序「建议收藏」依据ArcGIS组件式开发及应用的目录结构,将系统性的学习ArcGIS二次开发的道路分为三个部分。这个系列包含以下三个部分:Part1基础1.前言1.1组件式GIS1.2ArcObject开发的特点与历史2.使用ArcGISEngine控件编程3.几何形体对象Geometry4.地图组成5.空间数据符号化6.空间数据管理7.空间分析8.空间数据编辑9.地图输出10…

    2022年7月23日
    13
  • sql 未明确定义列_查询块具有不正确的结果列数

    sql 未明确定义列_查询块具有不正确的结果列数ORA-00918:未明确定义列:你在做多表查询的时候出现了字段重复的情况,因为你有时候会对字段进行重新命名,表A的A1字段与表B的B1字段同时命名成了C,这时候就会出现未明确定义列,假设A表中有一个字段名叫:A_B_C,实体类就会有个叫ABC的字段,sql你写成:SELECT*FROM(SELECTDISTINCTA.,B.B1ASABC这样写是没有问题的,但是:SELECT*FROM(SELECTDISTINCTA.,B.B1ASA_B_C就有问题了;

    2022年10月4日
    3
  • 欧拉角pitch、yaw,roll的理解_彻底搞懂四元数

    欧拉角pitch、yaw,roll的理解_彻底搞懂四元数目录0、简介一、四元数的定义二、欧拉角到四元数的转换2.1公式:2.2code:三、四元数到欧拉角的转换3.1公式3.2code:3.3四元素到旋转矩阵转换四.奇点五.矢量旋转证明:六.其他参考0、简介四元数与欧拉角之间的转换百度百科四元素在3D图形学中,最常用的旋转表示方法便是四元数和欧拉角,比起矩阵来具……

    2022年9月22日
    5
  • 迭代器Python_Python进阶

    迭代器Python_Python进阶迭代器迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。可迭代对象我们已经知道可以对l

    2022年7月30日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号