欧拉函数
定义: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<iostream>
#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<iostream>
#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;
}