欧拉函数
实现方面其实照着定义,分解质因数然后代入公式就可以了,这里主要解释一下这个公式可以怎么推出来:
一个正整数N,它可以被分解为若干质因数幂的乘积pa11∗pa22∗…∗pakk,换句话说,这些p1,p2,…,pk都可以整除N,那么对于与N互质的数D,这些质数就都不能整除D了。因此,可以求出在1∼N中随意选出一个数,它不能被上述质数中的任意一个整除,这个事件的概率有多大,然后用N乘上这个概率值,就可以得到欧拉函数ϕ(N)的值了。
首先,这个事件可以视作多个互相独立的事件Ai(从1∼N中选出一个数,使其不被质数pi整除)的交集,而考研数学的概率论中有这么一条关于独立事件A,B的规律:P(AB)=P(A)∗P(B),衍生到n个独立事件则可以得出下面的表达式:
P(A1A2A3…An)=P(A1)∗P(A2)∗P(A3)∗…∗P(An)=∏ni=1(P(Ai))
然后关注一下其中任意一个事件Ai,1∼N的正整数中,能被pi整除的数为{pi,2∗pi,3∗pi,…,m∗pi}共m个,其中m=N/pi,那么不能被pi整除的数就一共有N−N/pi个,对应Ai的概率就为1−1/pi。将所有互相独立的事件Ai的概率按照之前的表达式相乘,就可以得出从1∼N中选出一个数,使其不能被所有质数pi整除的概率就是(1−1/p1)∗(1−1/p2)∗…∗(1−1/pk)(默认向下取整),最后乘上N,并把减号移到分子上,就是ϕ(N)的表达式:
ϕ(N)=N∗p1−1p1∗p2−1p2∗…∗pk−1pk
C++ 代码
/**
* @brief 欧拉函数(即1~n中与n互质的数的个数)
* @param n 上限
* @return 函数值(已定义)
*/
size_t countSmallerCoprimeNumbers(int n) {
size_t cnt = n;
for (int i = 2; i <= n; i++) {
if (n % i == 0) { //这里一定要提前退出,因为无法整除的话cnt是没有必要计算的
continue;
}
cnt = cnt * (i - 1) / i;
while (n % i == 0) {
n /= i;
}
}
if (n > 1) {
cnt = cnt * (n - 1) / n;
}
return cnt;
}