首页 > 其他分享 >【数学】【模板】欧拉函数

【数学】【模板】欧拉函数

时间:2024-07-22 09:20:26浏览次数:12  
标签:right 函数 int dfrac varphi cdots 模板 欧拉 left

欧拉函数

思想

\(\varphi(n)\) 表示的是 \(1\sim n\) 中与 \(n\) 互质的个数。

怎么求 \(\varphi(n)\) 呢?

先将 \(n\) 质因数分解:\(n = p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}\),那么 \(\varphi(n) = n\left(1 - \dfrac{1}{p_1}\right)\left(1 - \dfrac{1}{p_2}\right)\cdots \left(1 - \dfrac{1}{p_k}\right)\)。

证明:

要保留所有 \(1\sim n\) 中与 \(n\) 互质的数字,需要用到容斥原理,如下:

  1. 删除 \(1\sim n\) 中所有 \(p_1, p_2, \cdots p_k\) 的倍数;
  2. 加上所有 \(p_ip_j\) 的倍数(\(i, j\) 互不相同);
  3. 减去左右 \(p_ip_jp_k\) 的倍数(\(i, j, k\) 互不相同);
  4. 加上所有 \(p_ip_jp_kp_l\) 的倍数 (\(i, j, k, l\) 互不相同)。

然后是减去 5 个质因数相乘,加上 6 个质因数相乘,以此类推。

展开 \(\varphi(n) = n\left(1 - \dfrac{1}{p_1}\right)\left(1 - \dfrac{1}{p_2}\right)\cdots \left(1 - \dfrac{1}{p_k}\right)\),然后发现就是上面那些操作。

也可以写成:\(\varphi(n) = n\cdot \dfrac{p_1 - 1}{p_1}\cdot \dfrac{p_2 - 1}{p_2}\cdots \dfrac{p_n - 1}{p_n}\)(感谢 @沃若 的建议)。

代码

void solve() {
	int x, ans;
	cin >> x;
	ans = x;
	for (int i = 2; i * i <= x; i++) {
		if (x % i == 0) {
			(ans /= i) *= (i - 1);
			while (x % i == 0) x /= i;
		} 
	}
	if (x > 1) (ans /= x) *= (x - 1);
	cout << ans << '\n';
}

\(O(n)\) 求欧拉函数

思想

即在线性筛的过程中求出所有数字的 \(\varphi\)。

首先,如果 \(x\) 是个质数,\(\varphi(x) = x - 1\),因为在 \(1\sim x\) 中除了 \(x\) 都与 \(x\) 互质。

然后,想一想怎么求 \(phi(i \cdot j)\),其中 \(i\) 是一个正数,\(j\) 是一个质数且是 \(i\cdot j\) 的最小质因数。

首先,如果 \(i\bmod j \ne 0\),那么证明 \(i\) 中也没有 \(j\),那么根据上面的公式:

\[\varphi(n) = n\left(1 - \dfrac{1}{p_1}\right)\left(1 - \dfrac{1}{p_2}\right)\cdots \left(1 - \dfrac{1}{p_k}\right) \]

我们发现 \(j\) 是第一次出现,所以要在 \(\varphi(i)\) 乘上 \(j \cdot \left(1 - \dfrac{1}{j}\right)\),根据乘法分配率,就是乘上 \(j - 1\)。

然后,根据上面的公式,假设 \(i \bmod j = 0\),那么证明 \(i\) 中已经有 \(j\) 了,已经出现过 \(\left(1 - \dfrac{1}{j}\right)\),所以不需要再乘了,我们只要乘上 \(j\) 就可以了。

特殊的,\(\varphi(1) = 1\)。

代码

const int N = 1000010;

bool inp[N];
int prime[N], cnt;
int phi[N];

void getprime(int n) {
    inp[0] = inp[1] = true;
    phi[1] = 1;

    for (int i = 2; i <= n; i++) {
        if (!inp[i]) {
            prime[++cnt] = i;
            phi[i] = i - 1;
        }

        for (int j = 1; j <= cnt && i * prime[j] <= n; j++) {
            inp[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}

标签:right,函数,int,dfrac,varphi,cdots,模板,欧拉,left
From: https://www.cnblogs.com/Yuan-Jiawei/p/18315353

相关文章

  • 【数学】【模板】欧几里得算法
    欧几里得算法思想\[\gcd(a,b)=\gcd(b,a\bmodb)\]证明\(\gcd(a,b)=\gcd(b,a\bmodb)\):首先,如果有\(d|a\),\(d|b\),那么\(d|ax+by\)。然后,\(a\bmodb=a-\left\lfloor\dfrac{a}{b}\right\rfloorb\)。假设\(p=\gcd(a,b)\),那么\(p|......
  • 【搜索】【模板】A* 算法
    学了IDA*,然后学学A*。A*A*可以简单理解为在bfs的时候分个先后,哪个最有可能先到达就先走哪一步。A*是在某个最短路问题中(比如求最小的步骤等),如果所有边权都是非负的,那么就可以使用启发函数来优化bfs过程。例题P1379八数码难题思路我们在bfs的过程中加入函数\(h......
  • 【数据结构】【模板】莫队
    莫队使用场景离线算法;区间询问不断修改。能用\(O(1)\)的时间复杂度从\([l,r]\)到\([l+1,r]\)或者\([l,r-1]\)。原理原问题可以转化为为建立一个坐标轴,对于一个询问\((l,r)\),相当于点\((l,r)\),从一个询问\((a,b)\)到\((c,d)\),可以理解为点\((a,b)......
  • 【图论】【模板】差分约束系统
    差分约束系统差分约束系统是将不等式组的问题转化为图论问题。前置知识判断负环例题P5960【模板】差分约束算法思路我们将\(x_u-x_v\ley_u\)换为\(x_u\lex_v+y_u\)。然后我们建立一条连接\(v,u\)(注意是\(v,u\)不是\(u,v\))权值为\(y_u\)的边。我们发......
  • 【图论】【模板】最长路、最短路
    最短路Dijkstra算法思路Dijkstra算法,采用贪心思想,在某一时刻如果\(dis\)数组中\(dis_u\)最小,那么就固定\(u\),\(dis_u\)一定是\(1\rightarrowu\)的最短路径,然后我们再通过\(u\)更新与\(u\)有边相连的\(v\),如果\(dis_v>dis_u+w\),那么\(dis_v=dis_u+w\)......
  • 【图论】【模板】判断负环
    使用SPFA算法判断负环前言判断负环是属于判定性的问题,常与二分结合起来。例题AcWing852.spfa判断负环思路可以使用SPFA进行判断。因为两点之间至多有\(n-1\)条边,所以当一个点的最短路径经过的边数大于等于\(n\)时,说明有负环。代码#include<bits/stdc++.h>......
  • 【搜索】【模板】模拟退火
    前置知识自然对数、分数次幂、概率。前言模拟退火可以在我们想不到题目正解的时候试一试其实就是骗分方法。因为纯随机得出正确答案的概率非常低,所以我们就可以加一定的优化,使找到答案概率增大。算法思想温度(步长):每次选择一个范围进行搜索,在搜索过程中范围不断缩小,最后到很......
  • C++ 中不应抛出异常的函数总结
    在C++中,异常处理是一个重要的特性,它允许程序在遇到错误时能够优雅地恢复。然而,并不是所有的函数都适合抛出异常。以下是一些不应抛出异常的函数类型:析构函数:析构函数负责资源的清理和释放。如果析构函数抛出异常,并且没有被捕获,那么程序可能会终止。这会导致资源泄露或程序......
  • 欧拉图、欧拉路径、欧拉回路
    P7771【模板】欧拉路径欧拉路径的模板题。思路首先判断是否有欧拉路径,然后排序,找出起点,最后dfs找路径。代码细节多,比如要判断一个点是否存在(这个题目不需要)。#include<bits/stdc++.h>usingnamespacestd;constintN=100010;vector<int>e[N];inthead[N],in......
  • 另一个函数的 lambda 函数但强制固定参数
    我刚刚从Matlab切换到Python,我想使用lambda函数将具有多个参数的函数f1(x,y)映射到一个参数函数f2(x)进行优化。我希望当我映射函数时f2(x)<-f1(x,y=y1)然后y无论发生什么变化都保持不变,在Matlab中默认情况下这是正确的,但如果我在P......