首先回顾线性筛法
void get_prime(int n)
{
for( int i = 2 ; i <= n; i++ )
{
if(!st[i]) primes[++cnt] = i;
for( int j = 1 ; primes[j] <= n / i ; j++ )
{
st[i * primes[j]] = true;
if( i % primes[j] == 0 ) break;
}
}
}
1.我们都知道质数的欧拉函数(即与其互质的数的个数)就是phi[N] = N - 1
2.然后根据i % primes[i] == 0
可以知道 其实i
和i * primes[j]
的质数的种类是一样的
差别在于后者的 质数中primes[j]
多了一次方因此我们可以推出phi[i * primes[j]] = primes[j] * phi[i]
;
3.接着我们就可以知道当i % primes[j]] != 0
时的欧拉函数函数的值了;因为primes[j]
不是他的因数,所以可以直接看做在i
的基础上又乘上了一个质数,所以他的欧拉函数就相当于primes[j] * phi[i] * (1 - (1 / primes[j]))
可以化为(primes[j] - 1) * phi[i]
因此就可以得到下面的代码来求出前N的数的欧拉函数的和了
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
int primes[N];
ll phi[N];
bool st[N];
int cnt;
int n;
ll get_oular(int n)
{
ll res = 0;
phi[1] = 1;
for (int i = 2; i <= n; ++i){
if(!st[i])
{
primes[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; ++j){
st[primes[j] * i] = true;
if(i % primes[j] == 0)
{
phi[primes[j] * i] = primes[j] * phi[i];
break;
}
phi[primes[j] * i] = (primes[j] - 1) * phi[i];
}
}
for (int i = 1; i <= n; ++i){
res += phi[i];
}
return res;
}
int main()
{
cin >> n;
cout << get_oular(n);
return 0;
}
感谢你的阅读 ^ - ^