版权声明:欢迎转载 https://blog.csdn.net/l18339702017/article/details/81879000
欧拉函数
欧拉函数
f(n) : 从1 ~ n 中与 n互质的数的个数
ll Euler(ll n){
ll ans = 1;
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
n /= i;
ans *= (i - 1);
while(n % i == 0){
n /= i;
ans *= i;
}
}
}
if(n > 1) ans *= (n-1);
return ans ;
}
欧拉线性筛
筛素数(时间复杂度要优于埃氏筛法)
void get_list(){
for(int i=2;i<=maxn;i++){
if(!is_not_pr[i]) prime[++tot]=i;
for(int j=1;j<=tot&&i*prime[j]<=maxn;j++){
is_not_pr[i*prime[j]]=1;//合数标为1,同时,prime[j]是合数i*prime[j]的最小素因子
if(i%prime[j]==0) break;//即比一个合数大的质数和该合数的乘积可用一个更大的合数和比其小的质数相乘得到
}
}
}
筛欧拉函数 + 素数
时间复杂度 O(n)
//欧拉线性筛:在线性时间内筛素数的同时求出所有数的欧拉函数
int tot;
int phi[MAXN];//保存各个数字的欧拉函数
int prime[MAXN]; //按顺序保存素数
bool mark[MAXN];//判断是否是素数
void get_phi(){
phi[1] = 1;
for(int i = 2; i <= MAXN; i++){//相当于分解质因数的逆过程
if(!mark[i]){
prime[++tot] = i;
phi[i] = i-1;
}
for(int j = 1; j <= tot; j++){
if(i * prime[j] > N) break;
mark[i * prime[j]] = 1;//确定i*prime[j]不是素数
if(i % prime[j] == 0){//判断prime[j] 是否为 i的约数
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else{//prime[j] - 1 就是 phi[prime[j]],利用了欧拉函数的积性
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
}