首页 > 其他分享 >欧拉函数

欧拉函数

时间:2024-05-21 17:34:09浏览次数:22  
标签:phi 函数 int 质数 varphi times prod 欧拉

一、欧拉函数

定义

\([1,n]\) 中与 \(n\) 互质的数的个数,称为欧拉函数,记为 \(\varphi(n)\)。

  • 互质的定义:对于正整数 \(a\) 和 \(b\),若 \(gcd(a,b)=1\),则 \(a\) 和 \(b\) 互质。

性质

  1. 若 \(p\) 是质数,则 \(\varphi(p)=p-1\)。
    证:因为 \(p\) 是质数,所以因数只有 \(1\) 和 \(p\)。对于 \([2,p-1]\),与 \(p\) 的公因数只能是 \(1\);对于 \(1\),\(gcd(1,p)=1\);显然,\(gcd(p,p)=p\)。所以,\(\varphi(p)=p-1\)。
  2. 若 \(p\) 是质数,则 \(\varphi(p^k)=(p-1)p^{k-1}\)。
    证:对于 \([1,p^k]\) 构成的数列,相当于以 \(p\) 个数作为一个单元:\(1...p...2p...3p......p^k\),一共有 \(\frac{p^k}{p}=p^{k-1}\) 个这样的单元。每个单元中,除了类似 \(p,2p,3p,...,p^k\) 这样的数,其它数都与 \(p^k\) 互质。所以,\(\varphi(p^k)=(p-1)p^{k-1}\)。
  3. 欧拉函数是积性函数,即满足 若 \(gcd(m,n)=1\),则 \(\varphi(mn)=\varphi(m)\varphi(n)\)。

计算公式

唯一分解定理:对于任意大于 \(1\) 的自然数 \(n\),可以分解为一系列质数之积,即 \(n=\prod_{i=1}^S{p_i^{a_i}},~~~~p_i为质数,~a_i为p_i的个数\)。

\[\varphi(n)=\begin{cases} 1&,n==1\\ n\times \prod_{i=1}^S{\frac{p_i-1}{p_i}}&,n\ge2 \end{cases} \]

注:仅由 \(n\) 和质因数 \(p_i\) 决定,与质因数个数 \(a_i\) 无关。

证:

\[\begin{split} \varphi(n)&=\varphi(\prod_{i=1}^S{p_i^{a_i}})\\ &=\prod_{i=1}^S{\varphi(p_i^{a_i})}~~~~由性质3\\ &=\prod_{i=1}^S{(p_i-1)p_i^{a_i-1}}~~~~由性质2\\ &=\prod_{i=1}^S{p_i^{a_i}(1-\frac{1}{p_i})}\\ &=\prod_{i=1}^S{p_i^{a_i}}\times \prod_{i=1}^S{(1-\frac{1}{p_i})}\\ &=n\times \prod_{i=1}^S{\frac{p_i-1}{p_i}}~~~~由唯一分解定理 \end{split} \]

二、求解算法

试除法

找到 \(n\) 的所有质因子,与 \(n\) 一起累乘即为所求。

int phi(int n)
{
    int res = n;

    for (int i = 2; i * i <= n; ++i)
    {
        if (n % i == 0)    // i是n的质因子
        {
            res = res * (i - 1) / i;

            while (n % i == 0)    n /= i;
        }
    }
    
    if (n > 1)    res = res * (n - 1) / n;
    
    return res;
}

筛法

该算法可以求出 \([1,n]\) 内所有数的欧拉函数。

算法简析

该算法基于线性筛

对于质数,若 \(i\) 是质数,则 \(phi[i]=i-1\)。

对于合数,在筛数时求欧拉函数。设当前枚举到 \(i\),遍历已知的质数 \(p_j\) 来筛数。令 \(m=i\times p_j\),则 \(phi[m]\) 为

  • 若 \(p_j\) 整除 \(i\),则 \(\varphi(m)=p_j\times\varphi(i)\)。
    证:因为 \(p_j\) 整除 \(i\),所以 \(i\) 包含 \(p_j\) 的所有质因子。又因为 \(m=i\times p_j\),所以 \(i\) 与 \(m\) 的质因子相同。

\[\begin{split} \varphi(m)&=m\times\prod_{k=1}^S{\frac{p_k-1}{p_k}}~~~~计算公式\\ &=p_j\times i\times\prod_{k=1}^S{\frac{p_k-1}{p_k}}\\ &=p_j\times\varphi(i) \end{split} \]

  • 若 \(p_j\) 不能整除 \(i\),则 \(\varphi(m)=(p_j-1)\times\varphi(i)\)。
    证:因为 \(p_j\) 不能整除 \(i\),则 \(i\) 与 \(p_j\) 互质。由性质1和2,则 \(\varphi(m)=\varphi(i\times p_j)=\varphi(p_j)\times\varphi(i)=(p_j-1)\times\varphi(i)\)。

Code

const int MAX = 1e8 + 5;
bool vis[MAX];      // vis[i] -- i是否筛去 
int p[MAX], cnt;    // p[] -- 存储质数; cnt -- 统计质数个数
int phi[MAX];       // phi[i] -- i的欧拉函数

void get_phi(int n)
{
	phi[1] = 1;
	
	for (int i = 2; i <= n; ++i)
	{
		if (!vis[i])
		{
			p[cnt++] = i;
			phi[i] = i - 1;
		}
		
		for (int j = 0; i * p[j] <= n; ++j)
		{
			int m = i * p[j];
			vis[m] = true;
			
			if (i % p[j] == 0)
			{
				phi[m] = p[j] * phi[i];
				break;
			}
			else
				phi[m] = (p[j] - 1) * phi[i];
		}
	}
}

标签:phi,函数,int,质数,varphi,times,prod,欧拉
From: https://www.cnblogs.com/hoyd/p/18204586

相关文章

  • python中那些双下划线开头得函数和变量
    Python中下划线---完全解读Python用下划线作为变量前缀和后缀指定特殊变量_xxx不能用frommoduleimport*导入__xxx__系统定义名字__xxx类中的私有变量名核心风格:避免用下划线作为变量名的开始。因为下划线对解释器有特殊的意义,而且是内建标识符所使用的符号,我们建议程......
  • 不同场景下的构造函数调用
    本文为对不同场景下的构造函数调用进行跟踪。构造函数默认情况下,在C++之后至少存在六个函数默认构造/析构函数,复制构造/复制赋值,移动构造/移动赋值。以下代码观测发生调用的场景#include<iostream>structFoo{Foo():fd(0){std::cout<<"Foo::Foo()this="<<......
  • 再探虚函数
    虚函数是一种成员函数,其行为可以在派生类中被覆盖,支持动态调用派发。使用示例代码如下:extern"C"{//避免operator<<多次调用,简化汇编代码voidprintln(constchar*s){std::cout<<s<<std::endl;}}void*operatornew(size_tn){void*p=malloc(n);......
  • c++ 结构体的构造函数
    结构体中构造函数1、不使用构造函数1#include<iostream>23structstudent{45intage;6std::stringgender;78}Liu;910intmain(){11Liu.age=20;12Liu.gender="man";1314std::cout<<Liu.age<......
  • Flink富函数
      富函数是DataStreamAPI提供的函数接口,Flink的函数都有它的Rich版本,它与其他函数不同的是,富函数可以获取到运行环境上下文,初始化参数,拥有生命周期方法等,可通过它进行自定义复杂功能。我们常见的如RichMapFunction、RichFilterFunction等。    富函数的生命周期主要通过......
  • 【代码】--库函数学习 temperature.c
    1. 封装的函数   用到了内核中的hwmon子系统,   hwmon子系统作为Linux内核中的一个子系统,用于监控硬件传感器的状态(设备的温度、电压和风扇转速)和提供对硬件传感器的访问接口。   在应用层,对传感器信息的读取,本质上是对驱动中hwmon子系统在注册传感器设备时所......
  • 方法:类似其它语言的函数
    方法:类似其它语言的函数方法的重载的规则:方法名称必须相同。参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。​顺序不同是指类型的顺序不同,与你起什么变量名无关,比如inta,intb与intb,inta就是相同顺序方法的返回类型可以相同也可以不相同。......
  • 函数对象、装饰器、闭包函数
    函数对象Python中一切皆对象【1】可以直接被引用定义一个函数用一个新的变量名来存,用新的变量名来调用【2】可以作为元素被储存功能字典的函数地址【3】函数可以作为参数传递给另一个函数将函数的内存地址作为参数传递【4】函数的返回值可以是函数直接将函数的内存地址返......
  • Oracle ORA-06575: 程序包或函数WM_CONCAT处于无效状态
    ------OracleORA-06575:程序包或函数WM_CONCAT处于无效状态----失效原因:版本不支持,WM_CONCAT是oracle的非公开函数,并不鼓励使用,新版本oracle并没有带此函数,需要手工加上。--首先使用dba账号登录oracle数据库sqlplussys/sysassysdba--解锁wmsys用户(可以是你自己定义的......
  • lodash已死?radash库方法介绍及源码解析 —— 函数柯里化 + Number篇
    写在前面tips:点赞+收藏=学会!主页有更多其他篇章的方法,欢迎访问查看。本篇我们继续介绍radash中函数柯里化和Number相关的方法使用和源码解析。函数柯里化chain:创建一个函数链并依次执行使用说明功能描述:用于创建一个函数链,该链依次执行一系列函数,每个函数的输出......