欧拉函数专题
欧拉函数专题
一、定义
定义:欧拉函数是小于的数中与互质的数的数目。
例如,因为均和互质。
解释:和是互质的。互质是指两个数的最大公约数为,而和的最大公约数就是,因此它们是互质的
二、公式
如果的唯一分解式:
有:
还是上面的栗子:
小结
下面三个公式,都需要依赖唯一分解定理:
- ① 约数个数:只与幂次相关,与质因子无关
约数个数
- ② 约数和:与质数子和幂次都相关
约数和=
- ③ 欧拉函数公式,只与因子相关,与指数无关!
欧拉函数=
三、欧拉函数公式证明
欧拉函数的证明是使用的融斥原理,从定义出发:
定义:欧拉函数是小于的数中与互质的数的数目。
- ① 对数字进行质因数分解:
- ② 如果一个数包含了这个因子,那么它肯定与不互质,因为有这个公因子嘛,换句话说,就是要想与互质,那么一定不能包含这些因子。
小于的所有数字中,如果它包含了这样的因子的话,那么它就与不互质,换句话说,只要把小于之内,所有包含的数字都干掉,剩下的就是与互质的数。所谓包含其实也就是 的整数倍。
- 把的倍数从中减去,那需要减去多少个呢?
答:个.
注:这里想不明白的话,可以举个栗子:比如,,有几个的倍数呢?个!为什么呢?
-
③ 把的倍数都减去吧,分别减去,,...,个。
-
④ 这么干是减多了的,比如某个数,是的倍数,也是的倍数,就减了两回,还需要再加回来的倍数,就是 + + + + ....
-⑤ 将公式展开,发现就是上面的东东了,证毕。
变形:
四、求单个数字的欧拉函数
#include <bits/stdc++.h>
using namespace std;
// 求单个数的欧拉函数值
int phi(int x) {
int res = x;
// 不要写在i*i<=x, 可能会造成爆int
for (int i = 2; i <= x / i; i++)
if (x % i == 0) { // 暴力枚举所有因子
res = res / i * (i - 1); // 套一下欧拉函数公式
while (x % i == 0) x /= i; // 只与质因子有关,与幂次无关,应除尽除
}
if (x > 1) res = res / x * (x - 1); // 最后一个大因子
return res;
}
int main() {
int n;
cin >> n;
while (n--) {
int x;
cin >> x;
printf("%d\n", phi(x));
}
return 0;
}
五、线性筛法求欧拉函数
依托于线性筛法,可以顺带求出欧拉函数值。如果对数论了解更多,会知道线性筛法还可以求出很多其它的东西。
- 。
被定义为
对区间内每个数进行分情况讨论:
- 如果这个数是质数,那么质数的欧拉函数值是
比如,那么当中有多少个数与互质呢?显然个都是嘛。
- 如果这个数不是质数,那么数字在被尝试筛的过程中:(这里设 以简便下面的书写)
推论:如果, 那么
证明:
【算术基本定理】
分解质数因数的结果,只比多分解了一个,而 说明中存在因子,只不过指数增加了个。
【欧拉公式】
我们发现,欧拉公式只与质数因子相关,而与质数因子的幂次无关! 二者的质数因子没有变化,变化的只是某个质数因子的幂次。所以:
证毕
推论: 如果, 那么
证明:
分解质数因数的结果,只是比多分解了一个,而 说明中不存在这个因子,需要写上去。
【证毕】
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
// 筛法求欧拉函数
// 这个东西就在欧兰筛的基础上,加上题解中证明的公式,只能是背下来,没有别的办法
int primes[N], phi[N], st[N];
int cnt, res;
void get_eulers(int n) {
phi[1] = 1; // 1的欧拉函数值是1,这个是递推的起点
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
phi[i] = i - 1; // ①质数,则phi(i)=i-1
}
for (int j = 0; primes[j] <= n / i; j++) {
int t = primes[j] * i;
st[t] = 1;
if (i % primes[j] == 0) {
phi[t] = phi[i] * primes[j]; // ② i%pj==0
break;
} else
phi[t] = phi[i] * (primes[j] - 1); // ③i%pj>0
}
}
}
signed main() {
int n;
cin >> n;
// 筛法求欧拉函数
get_eulers(n);
// 累加欧拉函数值
for (int i = 1; i <= n; i++) res += phi[i];
printf("%lld\n", res);
}
六、欧拉定理
和 为正整数,且 , 互素,即,则:
讲解视频
证明挺麻烦的,有兴趣可以看一看,我就不证明了~
用途
这个定理可以用来 简化幂的模运算。
基本例子
比如计算的个位数,实际是求被除的余数。和 互素 ,且。由欧拉定理知
所以
所以,答案是。
复杂例子
求的 个位 是什么。
很明显不可能直接把的结果计算出来,那样太大了。但我们想要确定的是,问题就简单了:
- 我们知道 =
- 因为要求的是末位,也就是的结果,想要使用 欧拉定理:
- 与互质
- ,需要想办法构造里面有多少个,可以直接把的倍数直接约掉:
根据 模运算规则 ,由于,我们得到
欧拉定理 出场!
对于而言,
中,即 (满足);
同时 满足 和互质,所以
所以
计算完毕,答案是。
七、一些性质
性质
当 时,
从定义上来证明:
假设有两个互质的正整数,则
因为互质,所以和各各都不相同,且都是的质因子
因此就可以推出
至此,积性函数的性质得证。但是由上面的证明可知,必须要互质才可以满足欧拉函数是 积性函数,由此可见 欧拉函数不是完全积性函数
性质
当 为奇数时,
证明
根据上面的性质,当 为奇数时, 与 互质,
又因为
所以
性质
若 , 则
性质
当时,所有小于且与互质的数和,并且 为偶数
证明
需要知道的一个基本事实是
注:关于这个,可以了解一下 更相减损术
也可以证明一下:
反证法,假设与互质,与不互质
设和的最大公约数为,则
所以,推导出和有公约数,与假设矛盾
因为 ,所以与互质的数都是 成对出现 的
每一对的和都为 。所以他们的和为 。
至于 为偶数。因为与 互质的数都是成对出现的,所以显然与 互质的数为偶数,即 为偶数。
性质
若 且 ,则
若且,则
证明
对于第一点
若 且 ,则证明 和 有相同的质因子,只是 这一项的指数不同
那么我们可以将其按照欧拉函数的计算式展开,并相除,可得:
对于第二点
若 且 ,则说明 与 互质(因为 为素数)
那么根据欧拉函数为积性函数的这个性质即可证得
证毕。
注: 这个性质广泛用于递推求欧拉函数,也就是筛法求欧拉函数的基础。
性质
设为一个正整数 ,
证明
列出
一共 个分数,再将他们化简.
最简分数在上面出现的话,当且仅当 且。
那么以为分母的分数共个。
分母一共被划分为 份.
所以
七、习题
题意:给定整数,求中与 不互质 的数的和,最后
看一下上面的性质证明,我们知道:设为中与互质的数的和
我们利用欧拉函数和欧几里德定理,if gcd(n,i)==1
,则有 gcd(n,n-i)==1
,可以知道其中一个若为,则存在一个为, 那么二者之和为 ,这样的一共有对, 故与互质的所有数的和为 ,那么与 不互质的数就是
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int MOD = 1e9 + 7;
// 求单个数值的欧拉函数值
int phi(int x) {
int res = x;
for (int i = 2; i <= x / i; i++) {
if (x % i == 0) {
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
}
if (x > 1) res = res / x * (x - 1);
return res;
}
signed main() {
int n;
while (cin >> n && n) {
// 小于n的数字中有多少个数字与n互质
int ans = n * (n - 1) / 2; // 高斯公式,(首页+末项)*项数/2
ans = (ans - phi(n) * n / 2) % MOD; // 扣除掉 phi(n)*n/2
cout << ans << endl;
}
}
#include <bits/stdc++.h>
using namespace std;
// https://blog.csdn.net/skywalkert/article/details/43955611
// https://www.cnblogs.com/shuguangzw/p/5697183.html
// 指数循环节问题
// https://blog.csdn.net/acdreamers/article/details/8236942
map<int, int> f;
int pow(int x, int k, int p) {
int ret = 1;
while (k) {
if (k & 1)
ret = (long long)ret * x % p;
x = (long long)x * x % p;
k >>= 1;
}
return ret;
}
int phi(int x) {
int ret = x;
for (int i = 2; i * i <= x; ++i)
if (x % i == 0) {
ret -= ret / i;
while (x % i == 0)
x /= i;
}
if (x > 1)
ret -= ret / x;
return ret;
}
int F(int x) {
if (f.count(x))
return f[x];
int p = phi(x);
return f[x] = pow(2, F(p) + p, x);
}
int main() {
int t, n;
scanf("%d", &t);
f[1] = 0;
while (t--) {
scanf("%d", &n);
printf("%d\n", F(n));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2017-09-01 数据遗留问题
2016-09-01 关于教育基础数据改造的一些想法
2015-09-01 分布式系统解决方案
2014-09-01 关于二级缓存的设计思路
2014-09-01 关于Sphinx中使用 RealTime Index的问题
2014-09-01 将Sphinx的日志放置到/dev/shm里需要注意的事情