定义:1 ∼ N 中与 N 互质的数的个数被称为欧拉函数,记为 ϕ(N)
公式:若 N = p1^a1 * p2^a2 * … * pk^ak 所有的pi都是N的质因数
那么 ϕ(N) = N * (p1-1)/p1 * (p2-1)/p2 * … *(pk-1)/pk;
性质 :
性质1:如果n是质数,那么ϕ ( n ) = n − 1 ,因为只有n本身与它不互质。
性质2:如果p,q都是质数,那么ϕ ( p ∗ q ) = ϕ ( p ) ∗ ϕ ( q ) = ( p − 1 ) ∗ ( q − 1 )
性质3:根据性质2得出,如果p是质数,那么ϕ ( p ^k ) = p ^k − p^ k − 1
1) 单个数的欧拉函数 :
原题链接:873. 欧拉函数 - AcWing题库
核心代码:
int res = n;
//利用了分解质因子的代码
for(int i=2;i<=n/i;i++){
if(n%i==0){
res = res*(i-1)/i;
while(n%i==0)n/=i;
}
}
完整代码:
#include
#define int long long
using namespace std;
signed main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int res = n;
for(int i=2;i<=n/i;i++){
if(n%i==0){
res = res*(i-1)/i;
while(n%i==0)n/=i;
}
}
if(n>1)res = res*(n-1)/n;
cout<<res<<endl;
}
return 0;
}
2)通过欧拉筛求欧拉函数
原题链接:874. 筛法求欧拉函数 - AcWing题库
问题: 给定一个正整数 n, 求 1∼n 中每个数的欧拉函数之和
证明:根据质因数定理 i = p1^a1 * p1^a2 . . . pk^ak
那么 ϕ( i ) = i*(a-1)/a * (a2-1)/a2 * … *(ak-1)/ak;
(1) 若是,i%p[ j ]==0,那么说明,p[ j ] 是 i 的一个质因子,那么 i* p[ j ] 的质因子与 i 是一摸一样的,区别只有i * p[ j ] 的质因子当中,p[ j ] 的次数多一个
所以,根据欧拉函数定义,i与i* p[ j ] 的欧拉函数是相同的,即phi[ i ] = phi[ i* p[ j ] ]
(2) 若是 ,i% p [ j ] != 0 ,那么说明,i *p[ j ] , 这个数比i 多了一个质因子 那么
ϕ ( i * p [ j ]) = p[ j ] * ϕ (i) * ( p[ j ] - 1 )/ p[ j ] = ϕ (i) * ( p[ j ] - 1 )
即 phi[ i ] = phi[ i* p[ j-1 ] ]
思路:利用欧拉筛可以筛到所有的合数的性质,我们求出可以求出每一位合数的欧拉函数
核心代码:
void prime(const int& n){
ph[1] = 1;
for(int i=2;i<=n;i++){
if(!st[i]){
p[res++] = i;
st[i] = true;
ph[i] = i-1;
sum+=ph[i];
}
for(int j=0;p[j]<=n/i;j++){
st[i*p[j]] = true;
if(i%p[j]==0){
ph[i*p[j]] = ph[i]*p[j];
sum+= ph[i*p[j]];
break;
}
ph[i*p[j]] = ph[i]*(p[j]-1);
sum+= ph[i*p[j]];
}
}
}
完整代码:
#include
#define int long long
using namespace std;
const int N =1000100;
bool st[N];
int ph[N],p[N];
int res;
int sum = 1;
void prime(const int& n){
ph[1] = 1;
for(int i=2;i<=n;i++){
if(!st[i]){
p[res++] = i;
st[i] = true;
ph[i] = i-1;
sum+=ph[i];
}
for(int j=0;p[j]<=n/i;j++){
st[i*p[j]] = true;
if(i%p[j]==0){
ph[i*p[j]] = ph[i]*p[j];
sum+= ph[i*p[j]];
break;
}
ph[i*p[j]] = ph[i]*(p[j]-1);
sum+= ph[i*p[j]];
}
}
}
signed main(){
int n;
cin>>n;
prime(n);
cout<<sum<<endl;
return 0;
}