欧拉函数
概念:欧拉函数是小于x的整数中与x互质的数的个数,一般用φ(x)表示。特殊的,φ(1)=1。
通式 :
φ
(
x
)
=
x
∏
i
=
1
n
(
1
−
1
p
i
)
,
φ
(
1
)
=
1
\varphi(x) = x\prod^{n}_{i = 1}(1 - \frac{1}{p_i}), \ \varphi(1) = 1
φ(x)=x∏i=1n(1−pi1), φ(1)=1
其中
p
1
,
p
2
,
.
.
.
.
.
p
n
p_1, p_2,.....p_n
p1,p2,.....pn为x的所有质因数(每个质因数只有一个),x为正整数
那么如何理解上面的式子呢?(转)
对于一个质因数
p
i
p_i
pi,因为x以内
p
i
p_i
pi的倍数是均匀分布的,所以x以内有
1
p
i
\frac{1}{p_i}
pi1的概率是
p
i
p_i
pi的倍数
那么有
1
−
1
p
i
1 - \frac{1}{p_i}
1−pi1的数不是
p
i
p_i
pi的倍数。
对于
p
j
p_j
pj,同理,有
1
−
1
p
j
1-\frac{1}{p_j}
1−pj1不是
p
j
p_j
pj的倍数,所以有
(
1
−
1
p
i
)
∗
(
1
−
1
p
j
)
(1 - \frac{1}{p_i}) * (1-\frac{1}{p_j})
(1−pi1)∗(1−pj1)的数既不是
p
i
p_i
pi的倍数,又不是
p
j
p_j
pj的倍数,最后就有
∏
n
i
=
1
(
1
−
1
p
i
)
\prod{n}{i = 1}(1-\frac{1}{p_i})
∏ni=1(1−pi1)的数与x互质,个数自然就是
x
∏
n
i
=
1
(
1
−
1
p
i
)
x\prod{n}{i = 1}(1-\frac{1}{p_i})
x∏ni=1(1−pi1)
举个例子,令x = 12。
12以内有
1
2
\frac{1}{2}
21的数是2的倍数,那么有
1
−
1
2
1-\frac{1}{2}
1−21的数不是2的倍数(1,3,,5,,7,,9,11)
这6个数又有
1
3
\frac{1}{3}
31的数是3的倍数,只剩下
(
1
−
1
2
)
∗
(
1
−
1
3
)
(1-\frac{1}{2}) * (1-\frac{1}{3})
(1−21)∗(1−31)的数既不是2的倍数,也不是3的倍数(1,5,7,11)
这样剩下来的
12
∗
(
1
−
1
2
)
∗
(
1
−
1
3
)
=
4
12 *(1-\frac{1}{2}) *(1-\frac{1}{3}) = 4
12∗(1−21)∗(1−31)=4,即有4个数与12互质。
实现代码:
(1)直接求不超过n的互质的个数
int euler(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ans = ans / i * (i - 1); //先进行除法防止溢出(ans = ans * (1 - 1 / p(i)))
while (n % i == 0) n /= i;
}
}
if (n ^ 1) // n != 1
ans = ans / n * (n - 1);
return ans;
}
(2)求[1,n]之间每个数的质因数的个数
const int size = 1e6;
int euler[size];
void Init() {
memset(euler, 0, sizeof(euler));
euler[1]=1;
for(int i = 2; i < size; i++)
if(!euler[i]) {
for(int j = i; j < size; j += i) {
if(!euler[j])
euler[j] = j;
euler[j] = euler[j] / i * (i - 1);//先进行除法是为了防止中间数据的溢出
}
}
}