欧拉函数
对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。例如euler(8)=4,因为1,3,5,7均和8互质。
Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。euler(1)=1(唯一和1互质的数就是1本身)。
欧拉公式的延伸:一个数的所有质因子之和是euler(n)*n/2。
那么如何变成实现欧拉函数呢?下面通过两种不同的方法来实现。第一种方法是直接根据定义来实现,同时第一种方法也是第二种筛法的基础。
第二种给出的是复杂度o(n)的线性筛。
//直接求phi
int get_phi(int c)
{
LL ans = c;
int m = sqrt(c+0.5);
for(int i = 2; i <= m; ++i)
{
if(c % i == 0)
{
ans = ans/i*(i-1);
while(c % i ==0)c/=i;
}
}
if(c > 1)ans = ans/c*(c-1);
return ans;
}
//线性筛法,快的飞起
bool vis[MAXN];
int prime[MAXN];
int phi[MAXN];
int tot;
void init()
{
memset(vis, false, sizeof(vis));
phi[1] = 1;
tot = 0;
for(int i = 2; i < MAXN; i ++)
{
if(!vis[i])
{
prime[tot ++] = i;
phi[i] = i - 1;
}
for(int j = 0; j < tot; j ++)
{
if(i * prime[j] >= MAXN) break;
vis[i * prime[j]] = 1;
if(i % prime[j] == 0)
{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else
{
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
}
附上素数筛
void get_prim()
{
for(int i = 2; i < MAXN; ++i)
{
if(!vis[i])prim[tot++] = i;
for(int j = 0; j < tot; ++j)
{
if(prim[j]*i > MAXN)break;
vis[i*prim[j]] = 1;
if(i%prim[j] == 0)break;
}
}
}