积性函数系列(一):欧拉函数

2024-04-04 17:38
文章标签 函数 系列 欧拉 积性

本文主要是介绍积性函数系列(一):欧拉函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本系列是数论篇章的第一篇(于是又挖了一个数论的坑orz),主要介绍、证明初等数论中一些重要的概念、结论。
在微积分学领域,积性函数指的是具有 f(ab)=f(a)f(b) f(ab)=f(a)f(b)的函数,在数论领域这个概念略有不同,仅定义在正整数上,它揭示了整数的很多性质。废话不多说,直奔主题。

为了区分通常意义上的函数,我们定义算数函数:

定义1.1 定义在所有正整数上的函数称为算数函数。
在整个积性函数篇里,不加说明地,我们总是讨论算数函数。

定义1.2 算术函数 f f如果满足对于任意两个互质的正整数 m m n n,均有 f(mn)=f(m)f(n) f(mn)=f(m)f(n),就称 f f为积性函数(或乘性函数)。如果对于任意两个正整数 m m n n,均有 f(mn)=f(m)f(n) f(mn)=f(m)f(n),就称为完全积性函数。

很容易找到一些trivial的积性函数,如 f(n)=1,f(n)=n,f(n)=n2 f(n)=1,f(n)=n,f(n)=n2,事实上所有的幂函数都是积性函数。

结合积性函数的定义和算数基本定理,很容易得到下面的定理:

定理1.1 如果 f f是一个积性函数,对于任意的正整数 n n有素数幂分解 n=p1a1p2a2...psas n=p1a1p2a2...psas,那么有 f(n)=f(p1a1)f(p2a2)...f(psas) f(n)=f(p1a1)f(p2a2)...f(psas)
证明:略,使用数学归纳法即可。

好了,介绍完了积性函数的基本概念,就开始介绍今天的主角,欧拉函数,它也被称为欧拉 ϕ ϕ函数。顾名思义,它是由欧拉首先研究的。

定义1.3 欧拉函数 ϕ(n) ϕ(n)定义为不超过 n n且和 n n互质的正整数的个数。

下面我们就来探讨欧拉函数在各个点上的取值。很容易得到对于素数 p p ϕ(p)=p1 ϕ(p)=p−1,那么反过来是不是也成立呢?

定理1.2 如果 p p是素数,那么 ϕ(p)=p1 ϕ(p)=p−1.反之,如果 p p是正整数且满足 ϕ(p)=p1 ϕ(p)=p−1,那么 p p是一个素数。
证明:前句可由互质定义得到,我们只证明后句。若 p p不是素数,那么或是1或是合数。而 ϕ(1)=1 ϕ(1)=1,但若 p p是合数,得有因子 0<d<p 0<d<p,而 p p不与自身互质,这使得和 p p互质的数至多只有 p2 p−2个,所以也不可能,故 p p是素数。

我们再进一步,看欧拉函数在素数的幂下的取值。实际上和素数幂 pn pn不互质的只有 p p的倍数,一共有 pn/p=pn1 pn/p=pn−1个,故 ϕ(pn)=pnpn1 ϕ(pn)=pn−pn−1

定理1.3 如果 p p是素数,那么 ϕ(pn)=pnpn1 ϕ(pn)=pn−pn−1

接下来我们讨论更一般的情况,为此,我们需要证明欧拉函数是一个积性函数。定理的证明依赖于同余的一些简单性质,由于本文是本系列的第一篇,所以这里尽量把需要用到的性质先给证一证。如果你对这些性质比较清楚,可以直接跳过下面的补充部分,直接进入定理的证明。

定义1.4 一个模 m m完全剩余系是一个整数的集合,使得任意整数恰和此集合中的一个元素模 m m同余。

引理1.4  m m个模 m m不同余的整数的集合构成一个模 m m的完全剩余系。
证明: 假设 m m个模 m m不同余的整数的集合不是一个模 m m的完全剩余系。那么可能存在整数 a a,使得集合中存在不止一个元素和 a a同余,但由于同余的性质,如果 a a b b m m同余,且 a a c c m m同余,那么必有 b b c c m m同余,和假设不符;那么可能存在整数 a a,使得集合中不存在元素和 a a同余,但模 m m的余数只有 m m种可能, a a否定了一种可能,意味着集合里的元素模 m m至多只有 m1 m−1个值,但集合中的 m m个元素互不同余,应有 m m个不同的值,和假设不符。故原假设成立。

由上述引理,容易得到 0,1,2,3,...,m1 0,1,2,3,...,m−1是模 m m的一个完全剩余系。

引理1.5 若 r1,r2,...,rm r1,r2,...,rm是模 m m的一个完全剩余系,且正整数a满足 gcd(a,m)=1 gcd(a,m)=1,则对任意整数b, ar1+b,ar2+b,...,arm+b ar1+b,ar2+b,...,arm+b都是模 m m的完全剩余系。
证明:由引理1.4,我们只需证明这m个数互不同余。取任意两个元素 ri,rj,ij ri,rj,i≠j相减,得 ari+b(arj+b)=a(rirj) ari+b−(arj+b)=a(ri−rj).
若我们有 ariarj(mod m) ari≡arj(mod m), 基于同余的性质,在 gcd(a,m)=1 gcd(a,m)=1的情况下,两边可以约去 a a,于是得到 rirj(mod m) ri≡rj(mod m),这和假设矛盾,故 ari,arj ari,arj 不同余,故引理成立。

有了引理1.5后,我们就可以比较方便地证明定理1.6。

定理1.6 设m,n是两个互质的正整数,那么 ϕ(mn)=ϕ(m)ϕ(n) ϕ(mn)=ϕ(m)ϕ(n).
证明:我们将 1,2,...,mn 1,2,...,mn从上往下,从左往右依次排列,每一列写m个数:
1  m+1 2m+1 ... (n1)m+1 1  m+1 2m+1 ... (n−1)m+1
2  m+2 2m+2 ... (n1)m+2 2  m+2 2m+2 ... (n−1)m+2
... ...
r  m+r 2m+r ... (n1)m+r r  m+r 2m+r ... (n−1)m+r
... ...
m  2m  3m     ...  nm m  2m  3m     ...  nm
从行的角度观察上式,考察第 r r行,由于 m m m m不互质,所以如果 r r不和 m m互质的话,整行都不与 mn mn互质,所以实际上我们只需考虑 ϕ(m) ϕ(m)行。而对于这些 r r m m互质的行,每一行实际上构成模 n n的完全剩余系,我们研究某行,为了方便,同样记为 r r。取第 k k个元素,即 (k1)m+r (k−1)m+r,记 (k1)m+r mod m=d (k−1)m+r mod m=d.
如果d和m互质,那么有 (k1)m+rd=λm (k−1)m+r−d=λm可知, (k1)m+r (k−1)m+r m m也互质,否则存在的因子必是 d d的因子(同除以该因子,两边应均为整数);反之,如果 d d m m不互质, (k1)m+r (k−1)m+r m m也不互质, d d m m的公因子也是它们的公因子。于是每一行都有 ϕ(n) ϕ(n)个因子。定理得证。

结合定理1.3和定理1.6,以及算数基本定理,我们可以求得任意正整数的欧拉函数值。

定理1.7 设 n=p1a1p2a2...pkak n=p1a1p2a2...pkak为正整数n的素数幂分解,那么 ϕ(n)=n(11/p1)(11/p2)...(11/pk) ϕ(n)=n(1−1/p1)(1−1/p2)...(1−1/pk).
证明:由定理1.1和1.6可得, ϕ(n)=ϕ(p1a1)ϕ(p2a2)...ϕ(pkak) ϕ(n)=ϕ(p1a1)ϕ(p2a2)...ϕ(pkak).由定理1.3可得, ϕ(pkak)=pkpk1 ϕ(pkak)=pk−pk−1,于是有
ϕ(n)=p1a1p2a2...pkak(11/p1)(11/p2)...(11/pk) ϕ(n)=p1a1p2a2...pkak(1−1/p1)(1−1/p2)...(1−1/pk)
=n(11/p1)(11/p2)...(11/pk) =n(1−1/p1)(1−1/p2)...(1−1/pk)

至此我们已经掌握了欧拉函数的值得求法。你是否对这么多的证明感到厌烦了,在进一步讨论欧拉函数的性质之前,我们转换一下角度,从程序设计的角度入手,看看如何实现计算欧拉函数。如果你对程序设计不感兴趣,可以直接跳过这部分内容。计算单个欧拉函数值的过程实际上就是对正整数 n n进行分解的过程,我们从2开始从小到大寻找 n n的因子,显然找到的最小的因子必是素数(否则会有更小的素因子),找到后把这个素因子全部约去,并计算 (11/p1) (1−1/p1),然后接着向前,由于之前的因子已经消去,我们仍能保证找到的因子是素数。完整的代码如下:

01 int euler(int x){
02     int res = x;
03     for(int i=2; i<(int)sqrt(x*1.0)+1; ++i)
04         if(x % i == 0){
05              res = res / i * (i - 1);
06              while(x % i == 0) x /= i;
07          }
08     if(x > 1) res = res / x * (x - 1);
09     return res;
10 }

下面给出求 1..maxn 1..maxn的所有欧拉函数值的程序,也非常简单,这里不再解释了。

1 for(int i=1; i<=maxn; ++i) phi[i] = i;
2 for(int i=2; i<=maxn; i+=2) phi[i] /= 2;
3 for(int i=3; i<=maxn; i+=2)
4     if(phi[i] == i){
5         for(int j=i; j<=maxn; j+=i)
6             phi[j] = phi[j] / i * (i - 1);
7     }

短暂的休息之后接着回到欧拉函数的性质中来。下面的定理表明,除了 n=1,2 n=1,2 ϕ(n) ϕ(n)都是偶数。

定理1.8 设 n n是一个大于2的正整数,那么 ϕ(n) ϕ(n)是偶数.
证明:由定理1.1和1.2可知,大于2的素数都是偶数,而所有高于1次的素数幂(包括2)都是偶数,而由定理1.7,所有大于2的合数的欧拉函数都可以分解成素数幂的乘积,所以也必定是偶数。

最后我们介绍一个非常重要的概念,和函数,它在后续的内容中也会发挥作用。

定义1.5 设 f f是一个算数函数,那么记 F(n)=d|nf(d) F(n)=∑d|nf(d)代表 f f n n中所有正因子处的值的和,则 F F称为 f f的和函数。

对于欧拉函数而言,它的和函数有很好的性质:

定理1.9 设 n n为一个正整数,那么 d|nϕ(d)=n ∑d|nϕ(d)=n.
证明:我们1..n的整数按照与n的最大公约数划分成若干个不相交的类,最大公约数为d的类记为 Cd Cd。那么 md m∈d当且仅当 gcd(n,m)=d gcd(n,m)=d,或者说 gcd(n/d,m/d)=1 gcd(n/d,m/d)=1,由于 1<=m<=n 1<=m<=n m/d m/d可以取到 1..n/d 1..n/d的所有数,于是符合条件的m的个数即为 ϕ(n/d) ϕ(n/d)。于是有
F(n)=d|nf(n/d) F(n)=∑d|nf(n/d),而 n/d n/d实际上取尽了n的所有因子,于是等价于 d|nf(d) ∑d|nf(d),定理得证。

关于积性函数和欧拉函数的基础讨论就到这里了,本系列的下一节将介绍其它的积性函数以及有趣的梅森素数。

这篇关于积性函数系列(一):欧拉函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/876429

相关文章

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言