并非盈数之和

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

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

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

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

package EULER23;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/9/21.
 * 完全数是指真因数之和等于自身的那些数。例如,28的真因数之和为1 + 2 + 4 + 7 + 14 = 28,因此28是一个完全数。
 * 一个数n被称为亏数,如果它的真因数之和小于n;反之则被称为盈数。
 * 由于12是最小的盈数,它的真因数之和为1 + 2 + 3 + 4 + 6 = 16,所以最小的能够表示成两个盈数之和的数是24。通过数学分析可以得出,所有大于28123的数都可以被写成两个盈数的和;尽管我们知道最大的不能被写成两个盈数的和的数要小于这个值,但这是通过分析所能得到的最好上界。
 * 找出所有不能被写成两个盈数之和的正整数,并求它们的和。
 * 思路:素数筛思想找出每个数对应的真因数和,找出全部盈数所能得到的小于28123的和,将和标识出来(两种方案),求未被标识的正整数和。
 *   方案一:找出全部盈数,遍历全部数,每一个数从盈数list的第一个开始减,判断差是否是盈数,如果是则标识,不是则减list里下一个盈数,直到判断出盈数和或list的盈数大于等于当前数,得到标识数组。
 *   方案二:从小到达遍历,若遇到盈数,则遍历其之后的数,如果是盈数与其相加,将和标识出来,得到标识数组。
 * 第一种比第二种快将近一倍
 */
public class EULER23 {
    public static void main(String[] args){
        long start = System.currentTimeMillis();
        List<Integer> divisors = new ArrayList<Integer>();
        divisors.add(0);
        for (int i=1;i<28123;i++){
            for (int j=i;j*i<28123;j++){
                int num = 0;
                try {
                    num = divisors.get(j*i);
                }catch (IndexOutOfBoundsException e){
                    divisors.add(num);
                }
                num += i;
                if (i!=1 && i!=j)
                    num += j;
                divisors.set(i*j,num);
            }
        }
        int[] divisorSum = new int[divisors.size()];
        //方案一
        List<Integer> abundant = new ArrayList<Integer>();
        for (int i=12;i<divisorSum.length;i++) {//12为最小盈数
            if (divisors.get(i)>i)
                abundant.add(i);
        }
        for (int i=24;i<divisorSum.length;i++){
            for (int j=0;j<abundant.size();j++){
                int another = i-abundant.get(j);
                if (i<=abundant.get(j))
                    break;
                if (divisors.get(another)>another){
                    divisorSum[i] = 1;
                    break;
                }
            }
        }
        //方案二
//        for (int i=12;i<divisorSum.length;i++){//12为最小盈数
//            if (divisors.get(i)<=i)
//                continue;
//            for (int j=i;j+i<divisorSum.length;j++){
//                if (divisorSum[i+j] == 1)
//                    continue;
//                if (divisors.get(j)>j){
//                    divisorSum[i+j] = 1;
//                }
//            }
//        }
        long sum = 0;
        for (int i=1;i<divisorSum.length;i++){
            if (divisorSum[i]==0) {
                sum += i;
//                System.out.println(i);
            }
        }
        System.out.println("Non-abundant sums:" + sum);
        long end = System.currentTimeMillis();
        System.out.print("总用时:"+(end-start)+"毫秒");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值