Project Euler 23 Non-abundant sums( 整数因子和 )


题意:
完全数是指真因数之和等于自身的那些数。例如,28的真因数之和为1 + 2 + 4 + 7 + 14 = 28,因此28是一个完全数。

一个数n被称为亏数,如果它的真因数之和小于n;反之则被称为盈数。

由于12是最小的盈数,它的真因数之和为1 + 2 + 3 + 4 + 6 = 16,所以最小的能够表示成两个盈数之和的数是24。通过数学分析可以得出,所有大于28123的数都可以被写成两个盈数的和;尽管我们知道最大的不能被写成两个盈数的和的数要小于这个值,但这是通过分析所能得到的最好上界。

找出所有不能被写成两个盈数之和的正整数,并求它们的和。

思路:此题与欧拉21题相似


/*************************************************************************
    > File Name: euler023.c
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年06月30日 星期五 19时30分05秒
 ************************************************************************/

#include <stdio.h>
#include <inttypes.h>

#define MAX_N 28123

int32_t isPrime[MAX_N + 10] = {0};      // 记录最小素数幂次方isPrime[24] = 8 (2^3)
int32_t prime[MAX_N + 10] = {0};        // 记录素数
int32_t d[MAX_N + 10] = {0};            // 记录整数分解约数和
int32_t abundantSum[MAX_N + 10] = {0};
int32_t vis[MAX_N + 10] = {0};

void Init() {
    for (int32_t i = 2 ; i <= MAX_N ; i++) {
        if (!isPrime[i]) {
            isPrime[i] = i;
            prime[++prime[0]] = i;
            d[i] = i + 1;
        }
        for (int32_t j = 1 ; j <= prime[0] ; j++) {
            if (i * prime[j] > MAX_N)   break;
            if (i % prime[j] != 0) {    // 在prime[j]还小于i的最小素因子时
                isPrime[i * prime[j]] = prime[j];
                d[i * prime[j]] = d[i] * d[prime[j]];
            } else {
                isPrime[i * prime[j]] = isPrime[i] * prime[j];
                d[i * prime[j]] = d[i] * (isPrime[i] * prime[j] * prime[j] - 1) / (isPrime[i] * prime[j] - 1);
                break;
            }
        }
    }
    for (int32_t i = 1 ; i <= MAX_N ; i++) {
        d[i] -= i;
        if (d[i] <= i)  continue;
        abundantSum[++abundantSum[0]] = i;
    }
    for (int32_t i = 1 ; i < abundantSum[0] ; i++) {
        for (int32_t j = i + 1 ; j <= abundantSum[0] ; j++) {
            if (abundantSum[i] + abundantSum[j] > MAX_N)    continue;
            vis[abundantSum[i] + abundantSum[j]] = 1;
        }
    }
}
int32_t main() {
    Init();
    int32_t sum = 0;
    for (int32_t i = 1 ; i <= MAX_N ; i++) {
        if (vis[i]) continue;
        sum += i;
    }
    printf("%d\n",sum);
    return 0;
}

转载于:https://www.cnblogs.com/WArobot/p/7100502.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值