欧拉函数能求出不大于n且与n互质的数的个数
直接求法
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll maxn = 5e6 + 7;
const ll mod = 1e9 + 7;
ll phi(ll n)
{
ll m = n;
for(int i = 2; i * i <= n; i ++)
{
if(n % i == 0)
{
m = m / i * (i - 1);
while(n % i == 0)n /= i;
}
if(n == 1)break;
}
if(n > 1)m = m / n * (n - 1);
return m;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll n;
cin >> n;
cout << phi(n) << endl;
return 0;
}
线性筛法 时间复杂度(o(nloglogn)
void init()
{
phi[1] = 1;
for(int i = 2; i <= maxn; i ++)
{
if(!phi[i])
{
for(int j = i; j <= maxn; j += i)
{
if(!phi[j])phi[j] = j;
phi[j] = phi[j] / i * (i - 1);
}
}
}
}
欧拉筛法时间复杂度(o(n))
ll phi[maxn];
bool flag[maxn];///标记数组
ll p[maxn];///素因子的值
ll cnt = 0;
void Get_phi()///筛法求欧拉函数
{
cnt = 0;
memset(flag, true, sizeof(flag));
phi[1] = 1;
for(int i=2; i<maxn; i++)///线性筛法
{
if(flag[i])///素数
{
p[cnt++] = i;
phi[i] = i-1;///素数的欧拉函数值是素数 - 1
}
for(int j=0; j<cnt; j++)
{
if(i*p[j] > maxn)
break;
flag[i*p[j]] = false;///素数的倍数,所以i*p[j]不是素数
if(i%p[j] == 0)///性质:i mod p == 0, 那么 phi(i * p) == p * phi(i)
{
phi[i*p[j]] = p[j] * phi[i];
break;
}
else
phi[i*p[j]] = (p[j]-1) * phi[i];///i mod p != 0, 那么 phi(i * p) == phi(i) * (p-1)
}
}
}