专栏文章
【学习笔记】欧拉函数基础
算法·理论参与者 3已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 2 份
- 快照标识符
- @mjek1ufj
- 此快照首次捕获于
- 2025/12/21 01:11 2 个月前
- 此快照最后确认于
- 2026/01/22 01:23 4 周前
欧拉函数的定义
欧拉函数的基本性质
- 如果 为质数,那么 的值为 。
- 若 与 互质,那么 ,这是因为欧拉函数是积性函数。
- 若 为质数,那么 。
欧拉函数的计算公式
根据唯一分解定理
=
=
注意:欧拉函数只和 的质因子有关系。
例子
实际上 到 中,与 互质的数有 共 个。
φ函数的实现
不优化版
我们已经知道了欧拉函数的公式为
而且欧拉函数只和 的质因子有关系,那么我们可以一个一个枚举 的质因子,再乘上 就可以得到了;注意: 每找到一个质因子 时,一定要把 的 除尽为止。
Code
CPPint phi(int n){
int res=n;//res初始化为n
for(int i=2;i*i<=n;i++){//枚举可能的因子
if(n%i==0){//如果i是因子(这里一定是质数,不然在前面已经被筛过了)
res=res/i*(i-1);//应用欧拉函数的公式
while(n%i==0)//除尽所有i的因子
n/=i;
}
}
if(n>1)//处理剩余的质因子
res=res/n*(n-1);
return res;//返回res
}
线性优化版
我们可以优化——用线性筛法进行优化,我们知道线性筛法的方法只筛到一个最小的质因数就标记,所以我们可以通过线性筛来优化欧拉函数。
具体的
若 为质数,那么 ,并记录质数。
在线性筛中,每个和数 都是被最小的质因子筛掉的。
设 是 的最小质因子,则 是通过 筛掉的。
在线性筛中,每个和数 都是被最小的质因子筛掉的。
设 是 的最小质因子,则 是通过 筛掉的。
- 若 能被 整除,则 包含了 的所有质因子。
。 - 若 不能被 整除,则 和 是互质的。
。
Code
CPPconst int N=1000005;
int p[N],vis[N],cnt,phi[N];
void g_phi(int n){//欧拉筛法求1到n的phi值
phi[1]=1;//1的欧拉函数值为1
for(int i=2;i<=n;i++){
if(!vis[i]){//i为质数
p[++cnt]=i;//记录质数
phi[i]=i-1;//指数的phi值为i-1
}
for(int j=0;i*p[i]<=n;j++){//用i和所有质数p[j]的乘积筛
int m=i*p[j];
vis[m]=1;//m为非质数
if(i%p[j]==0){//如果i为p[j]的倍数
phi[m]=p[j]*phi[i];//根据欧拉函数的积性性质计算
break;//跳出内层循环
}
else
phi[m]=(p[j]-1)*phi[i];
}
}
}
例题
互质
这题只要认真看上面我介绍的都可以做出来,是一道水题主要是真的不知道写啥了。
思路
因为我们已经知道它要求的数是在 中有多少个数和 互质,根据欧拉函数的计算公式。
第一步我们可以先分解质因数:
第二步我们可以通过欧拉函数的性质转化成:
因为我们已经知道它要求的数是在 中有多少个数和 互质,根据欧拉函数的计算公式。
第一步我们可以先分解质因数:
第二步我们可以通过欧拉函数的性质转化成:
我们再用快速幂结合欧拉函数就好啦!
ACのCode
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
const int Mod=1e9+7;
int qpow(int a,int b){//快速幂
int ans=1;
a%=Mod; //初始值取模
while(b>0){
if(b%2==1) ans=(ans*a)%Mod;
a=(a*a)%Mod;
b/=2;
}
return ans;
}
signed main(){
int k1=2023*(7-1)/7*(17-1)/17; //phi[2023]
int k2=qpow(2023,2022); //计算2023的2022次方模Mod
cout<<(k1*k2)%Mod;
return 0;
}
互质数的个数
思路
这题是一道基础的欧拉函数的题目,通过观察直接看题目,我们就可以想到上文的基本性质三。
若 为质数,那么 。
然后我们看到数据范围是:,这我们想到了快速幂,然后再搭配欧拉函数 我们就可以做出这题了。
时间复杂度分析:
如果不用线性优化 会不会超时呢?我们知道欧拉函数(不优化)的复杂度是 ,通过计算,最大的复杂度也只是来到了 左右,所以不会超时。
ACのCode
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int qpow(int p,int k){//快速幂
int res=1;
while(k){
if(k&1)res=(res*p)%mod;
p=(p*p)%mod;
k>>=1;
}
return res;
}
int phi(int n){//phi函数
int res=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
res=res/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)res=res/n*(n-1);
return res;
}
signed main(){
int a,b;
cin>>a>>b;
int ans=(qpow(a,b-1)*(phi(a)%mod))%mod;
cout<<ans;
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...