欧拉函数和筛法求欧拉函数

Posted on 2022-04-06 20:10  ZheyuHarry  阅读(63)  评论(0编辑  收藏  举报

让我们先来看到欧拉函数的定义:

 

 我们相当于已经知道了公式只需要按照公式进行质因式分解即可,直接来看代码吧:

#include<bits/stdc++.h>

using namespace std;

int main()
{
int n;
cin >> n;
while(n -- ){
int a;
cin >> a;
int res = a;
for(int i = 2;i<=a/i;i++){
if(a%i == 0){
res = res/i*(i-1);
while(a%i == 0) a/=i;
}
}
if(a>1) res = res/a*(a-1);
cout << res << '\n';
}
return 0;
}

 

 

已知这个了,我们再接下去看看如果要求1~n的欧拉函数之和又该怎么求呢,如果一个个的去按上面的方法算很明显是会卡时间的,所以我们就要敏捷的发现其中的关系,我们可以发现其中合数的欧拉函数和质数仿佛有着一些微妙的关系,那么我们可以推导看看:

if(i%prime[j] == 0) 则phi[prime[j]*i] = phi[i]*prime[j],因为phi[i]中包含了所有prime[j]*i的因数,所以只需要扩大最外面的N即可!

else 则phi[prime[j]*i] = phi[i]*prime[j] *(prime[j] - 1)/prime[j] = phi[i] * (prime[j] - 1);

我们再看到phi[prime[j]] = prime[j] *(prime[j] - 1)/prime[j] = prime[j] - 1;

phi[1] = 1;

所以我们可以发现其实我们并不需要真正的去求任何一个数的欧拉函数都是有着直接的关系的!

 

代码:

#include<bits/stdc++.h>
#define maxn 1000001

using namespace std;
int prime[maxn],cnt;
bool st[maxn];
int phi[maxn];
typedef long long LL;

LL get_eulers(int n){
phi[1] = 1;
for(int i = 2;i<=n;i++){
if(!st[i]) {
prime[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0;prime[j]<=n/i;j++){
st[prime[j]*i] = true;
if(i%prime[j] == 0){
phi[prime[j]*i] = phi[i] * prime[j];
break;
}
phi[prime[j]*i] = phi[i] * (prime[j] - 1);
}
}
LL ans = 0;
for(int i = 1;i<=n;i++) ans+=phi[i];
return ans;
}

int main()
{
int n;
cin >> n;
cout << get_eulers(n) << '\n';
return 0;
}