72 Counting Fractions

Problem 72

考虑分数 , 其中 是正整数。如果 并且最大公因数 , 它被称作一个最简真分数。

如果我们将 的最简真分数按照大小的升序列出来,我们得到: 可知该集合中共有 21 个元素。

的最简真分数集合中包含多少个元素?

如果写代码就是遍历 ,然后针对每个 求 1 到 中有多少个数与 互质(互质才能是最简真分数),求和。

假设我们有一个函数能够得到互质数的个数,那么这个题目很容易解决,代码如下:

long count = 0;
for (int d = 2; d <= 1000000; d++)
{
    count += Utils.GetCoprimeCount(d);
}

return count;

现在关键问题是,给定一个数 ,如何求出 1 到 中,有多少个数与之互质。

欧拉函数描述了这个问题的解: 其中 的所有质因数。 又 所以

开始写代码实现欧拉函数求互质数的个数:

public static int GetCoprimeCount(int n)
{
    int ret = 1;
    for (int i = 2; i * i <= n; i++)
    {
        if (n % i == 0)
        {
            n /= i;
            ret *= i - 1;
            while (n % i == 0)
            {
                n /= i;
                ret *= i;
            }
        }
    }

    if (n > 1)
    {
        ret *= n - 1;
    }

    return ret;
}
简单解释两点。

if (n % i == 0) 里面的 ret *= i - 1; 相当于 里面的 while 里面的 ret *= i; 相当于 ,整个 while 循环就相当于

后面的 if 是判断,如果 ,那么剩余的 肯定是质数,ret *= n - 1; 就相当于 ,与之对应的 是 1。