欧拉计划第12题

Highly divisible triangular number

The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1+2+3+4+5+6+7=28. The first ten terms would be:

1,3,6,10,15,21,28,36,45,55,…

Let us list the factors of the first seven triangle numbers:

1: 1

3: 1,3

6: 1,2,3,6

10: 1,2,5,10

15: 1,3,5,15

21: 1,3,7,21

28: 1,2,4,7,14,28

We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?

三角形数是通过累加自然数所得到的数。例如,第7个三角形数是1+2+3+4+5+6+7=28。前十个三角形数分别是:

1,3,6,10,15,21,28,36,45,55,…

列举出前七个三角形数的所有约数:

1: 1

3: 1,3

6: 1,2,3,6

10: 1,2,5,10

15: 1,3,5,15

21: 1,3,7,21

28: 1,2,4,7,14,28

可以看出,28是第一个约数数量超过五的三角形数。

第一个约数数量超过五百的三角形数是多少?

这个题主要求的是一个数的约数,一个质数的约数等于1和他本身,那么一个合数呢这就是这题的关键所在:

一个合数等于他的质因子的幂次相乘的来的,你通过我之前的线性筛就可以发现这个问题线性筛,比如

4 = 2 * 2 = 2 ^ 2\\ 8 = 2 * 4 = 2 ^ 3\\ 6 = 2 * 3 = 2 ^ 1 * 3 ^ 1\\ 12 = 2 * 6 = 2 ^ 2 * 3 ^ 1

通过这个性质可以去求得合数的因子,继续往下看,现在把36作为一个例子

36 = 2 * 2 * 3 * 3 = 2 ^2 * 3 ^ 2\\ 36 = 2 ^ 0 * 2 ^ 2 * 3 ^ 2\\ 36 = 2 ^ 1 * 2 ^ 1 * 3 ^ 2\\ 36 = 2 ^ 0 * 3 ^ 1 * 2 ^ 2 * 3 ^ 1\\ 36 = 2 ^ 2 * 2 ^ 0 * 3 ^ 2\\ 36 = 2 ^ 1 * 3 ^ 1 * 2 ^ 1 * 3 ^ 1

你会通过发现从上往下可以得到

36 = 1 * 36\\ 36 = 2 * 18\\ 36 = 3 * 12\\ 36 = 4 * 9\\ 36 = 6 * 6\\

这就是一个36的所有因子,你可以发现他用他质因子的幂次可以得到所有的因子,但是怎么去计算呢,不可能一步一步算出来吧;

现在你把2^2和3^2看为一个集合,他们可以得到的因子是不是笛卡尔积?

所以最终F(36) = (2^0, 2^1, 2 ^2) * (3 ^ 0, 3 ^1, 3 ^ 2) = 3 * 3 = 9

所以不难发现,一个合数的因子个数等于他质因子的幂加一相乘的来的

所以得到公式 

F(N) = \prod_{1}^{n} (ai + 1)ai 表示质因子的幂次,n代表第n个质因数

现在假如A 和 B互质,求F(A * B) = ?

AB互质说明什么,说明他们没有共同的质因子比如3 和 5

所以他们之间的F(N)是互不影响的所以

F(A * B) = F(A) * F(B)

得到了这些性质,可能还是不会如何去编写代码,如果你对我之前线性筛的方法理解并且自己实现了,那对于下面的代码你肯定能看懂

#include <stdio.h>
#define MAX_N 20000
int prime[MAX_N + 5];
int f[MAX_N + 5];//因子个数
int cnt[MAX_N + 5];//当前数最小质因次的幂次


int main() {
    f[1] = 1;
    for (int i = 2; 2 * i <= MAX_N; i++) {
        if (!prime[i]) {
            prime[++prime[0]] = i;
            f[i] = 2;
            cnt[i] = 1;
        }
        for (int j = 1; i * prime[j] <= MAX_N; j++) {
            prime[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                f[i * prime[j]] = f[i] / (cnt[i] + 1) * (cnt[i] + 2);//因为prime[j]为i的最小质因子,根据刚才求合数的因子的公式,你先把之前prime[j]乘上的,然后在加一再乘上就可以得到对应的数的因子数了;
                cnt[i * prime[j]] = cnt[i] + 1;
                break;
            } else {
                cnt[i * prime[j]] = 1;//因为prime[j] 为他的最小质因子,所以对于最小质因子的幂次为1次
                f[i * prime[j]] = f[i] * f[prime[j]];//这里用了两个数互质等于他们因子数相乘
            }
        }
    }  
    for (int i = 1; i < 100; i++) printf("f[%d] = %d\n", i, f[i]);
    //得到每个数因子个数后可以来求当前题目的答案了
    int n = 1, fns = 0;  
    // 三角形数 = n * (n + 1) / 2;很容易知道n和n + 1是互质的所以三角形数的质数可以用下面的方式表示
    while (1) {
        if (n & 1) fns = f[n] * f[(n + 1) / 2];// n为奇数 n + 1就为偶数
        else  fns = f[n / 2] * f[n + 1];
        if (fns > 500) break;
        n++;
    }
    printf("%d %d\n", n * (n + 1) / 2, fns);
    return 0;
}

最终答案:76576500 他的因子个数为576

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初猿°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值