求解亲和数

本文介绍了如何高效计算一个正整数的真约数之和,提出了一种遍历到平方根的优化方法,并提供了Java代码示例。重点在于处理较大数值时的效率提升。
摘要由CSDN通过智能技术生成

  【问题描述】

  古希腊数学家毕达哥拉斯在自然数研究中发现,220的所有真约数(即不是自身 的约数)之和为: 1+2+4+5+10+11+20+22+44+55+110=284。而284的所有真约数为1、2、4、71、142,加起来恰好为220。人 们对这样的数感到很惊奇,并称之为亲和数。一般地讲,如果两个数中任何一个数都是另一个数的真约数 之和,则这两个数就是亲和数。

  220和284是人类最早发现,又是最小的一对亲和数。第二对亲和数(17296,18416)直到2000多年后的1636年才由法国数学家费马发现。1638年,法国数学家笛 卡儿发现了第三对亲和数,而大数学家欧拉在1747年一下子给出了30对亲和数, 1750年又增加到60对。到目前为止,人类已经发现了近千对亲和数。然而,令人惊 奇的是,第二对最小的亲和数(1184,1210)竟然被数学家们遗漏了,直到1886年才 由意大利的一位16岁男孩发现。

  这里不要求你找到一对亲和数,而是对于每个正整数n,求出这个数的真约数之和。

  比如,n=220,答案是284,如果n=284,答案是220。

  【输入形式】

  有多组测试数据,每组测试数据一行,是一个正整数n, n=0意味着输入结束并且不需要处理。

  40%的测试数据1 ≤ n≤ 10(3);30%的测试数据1 ≤ n≤ 10(4);

  20%的测试数据1 ≤ n≤ 10(5);10%的测试数据1 ≤ n≤ 10(6);

  【输出形式】

  对于每组测试数据,输出一行,包含一个正整数,表示n的真约数之和。

  【样例输入】

220
284
0

  【样例输出】

284
220

解题思路

问题关键:如何高效地找到一个数的所有真约数之和。一个直观的方法是遍历从1到n-1的所有数,检查它们是否是n的约数,并计算它们的和。然而,这种方法在n非常大时会非常慢。更高效的方法是只遍历到\sqrt{n},因为大于\sqrt{n}的约数可以通过n / 约数 得到。这样可以显著减少计算量。

  1. 对于每个输入的正整数n,初始化一个变量sum来存储真约数之和,初始值为1(因为1是所有正整数的真约数)。

  2. 从2遍历到\sqrt{n},对于每个i,检查它是否是n的约数。

    1. 如果i是n的约数,检查i是否等于 n / i(即检查是否是平方根)。

      • 如果是,只加i到sum(因为在这种情况下,i和 n / i实际上是同一个数)。

      • 如果不是,将 i 和 n / i 都加到sum。

  3. 特别注意,如果n为1,其真约数之和应为0,因为1没有真约数。

  4. 输出sum。

Java代码

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            int n = scanner.nextInt();
            if (n == 0) break; // 输入结束
            System.out.println(sumOfDivisors(n));
        }
        scanner.close();
    }

    // 计算并返回n的真约数之和
    private static int sumOfDivisors(int n) {
        if (n == 1) return 0; // 1没有真约数
        int sum = 1; // 所有数都至少有一个真约数1
        // 只需要检查到sqrt(n),因为大于sqrt(n)的约数可以通过n / 约数得到
        for (int i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                sum += i;
                if (i != n / i) { // 避免平方根被加两次
                    sum += n / i;
                }
            }
        }
        return sum;
    }
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值