尤拉函式和篩法求尤拉函式
讓我們先來看到尤拉函式的定義:
我們相當於已經知道了公式只需要按照公式進行質因式分解即可,直接來看程式碼吧:
#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;
}