求完美数

一个数如果恰好等于它的因子之和,这个数就称为"完美数"或"完数"。例如6=1+2+3.(6的因子是1,2,3) 完美数的一些性质:

  1. 欧几里德证明了:一个偶数是完数,当且仅当它具有如下形式:2(p-1)×(2p-1) 其中p和(2p-1)是素数。 尽管没有发现奇完数,但是当代数学家奥斯丁·欧尔(Oystein Ore)证明,若有奇完全数,则其形状必然是12p+1或36p+9的形式,其中p是素数。在1018以下的自然数中奇完数是不存在的。
  2. 除6以外的偶完数,把它的各位数字相加,直到变成一位数,那么这个一位数一定是1(亦即:除6以外的完数,被9除都余1) 28:2+8=10,1+0=1 496:4+9+6=19,1+9=10,1+0=1
  3. 因为 2p 是 2的幂,用C语言也就是1 << p,那么 2p-1 的二进制也就是p个1组成了,而 2(p-1) 是 2的幂,这两个数相乘,也就相当于把 2p-1 向左移 p-1 位,即 (2p-1) << (p-1),那所有完美数的二进制就是前面p个1,后面跟着p-1个0。 所以偶完数都可以表达为2的一些连续正整数次幂之和,如: 6=2(1 ) +   2(2 ) 28=2(2  ) +   2(3)   +   2(4) 8128=2(6)   +   2(7)   +   ...   +   2(12) 33550336=2(12)   +   2(13 )  +   ...   +   2(24)
    j = ((1 + (i ^ (i-1) )) >> 1) + i - 1;
    (j & (j + 1)) || (i & 1)
    上面的代码可以判断整数i是否是前面1后面0的形式。
  4. 每一个偶完数都可以写成连续自然数之和: 6=1+2+3 28=1+2+3+4+5+6+7 496=1+2+3+…+30+31
  5. 除6以外的偶完数,还可以表示成连续奇数的立方和(被加的项共有): 28 = 1(3) + 3(3) 496 = 1(3) + 3(3) + 5(3) + 7(3) 8128 = 1(3) + 3(3) + 5(3) + ... + 15(3) 33550336 = 1(3) + 3(3) + 5(3) + ... + 125(3) + 127(3)
  6. 每一个完数的所有约数(包括本身)的倒数之和,都等于2: 1/1 + 1/2 + 1/3 + 1/6 = 2 1/1 + 1/2 + 1/4 + 1/7 + 1/14 + 1/28 = 2

了解了上面一些性质后,就可以简单的来写一个求完美数的程序了。

#include <stdio.h>

#ifndef WIN32
typedef long long ll;
#else
typedef __int64 ll;
#endif

int main(void)
{
	ll i, j, n, x;

	for (n = 2; n <= 31; n++)
	{
		x = (1 << n) - 1;
		for(i = 3; i*i <= x; i += 2)
			if(x % i == 0)
				break;
		if(i*i <= x) continue;
		printf("%lld/n", (1 << (n - 1)) * x);
	}

	return 0;
}

运行结果:

6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128

到目前为止,已经求出的2p-1是素数的有25个:2、3、5、7、13、17、19、31、61、89、107、127、521、607、1279、2203、2281、3217、4253、4423、9689、9941、11213、19937、21701。 据说最后一个即221701-1是1978年两名美国大学生新发现的截止目前为止最大的一个素数 所有我们可以利用这个结果来求已知的完美数:

import java.math.BigInteger;

public class Main
{
	public static void main(String[] argv)
	{
		int [] prime = {
			2,3,5,7,13,17,19,31,61,	89,107,127,
			521,607,1279,2203,2281,3217,4253,
			4423,9689,9941,11213,19937,21701
		};
		BigInteger x = BigInteger.ONE;
		for (int i = 0; i < prime.length; i++)
			System.out.println(x.shiftLeft(prime[i]-1).multiply(x.shiftLeft(prime[i]).subtract(x)));
	}
}

最后一个完美数的长度是13066!堪称是BinIntegest


版权声明

本人的所有原创文章皆保留版权,请尊重原创作品。
转载必须包含本声明,保持本文完整,并以超链接形式注明原始作者“redraiment”和主站点上的本文原始地址。

联系方式

我的邮箱,欢迎来信(redraiment@gmail.com
我的Blogger(子清行
我的Google Sites(子清行
我的优快云博客(梦婷轩
我的百度空间(梦婷轩

<think>好的,我现在需要帮助用户解决如何用Python编写程序来完美的问题。首先,我得回忆一下什么是完美完美一个恰好等于它的真因子之和,比如6的真因子是1、2、3,而1+2+3=6,所以6是完美。接下来,用户需要的是方法或代码示例,所以我应该先解释完美的定义,再给出实现步骤。 首先,我得确定如何判断一个是否是完美。步骤应该是:对于给定的n,找出所有真因子(即除了n本身之外的约),然后和,检查是否等于n。例如,28也是一个完美,它的真因子是1、2、4、7、14,相加为28。 接下来,我需要考虑如何高效地找出这些真因子。传统的方法是遍历从1到n-1的所有,检查是否能整除n。但这样效率不高,尤其是当n很大时。优化方法是遍历到sqrt(n),因为因子是成对出现的。例如,如果i是n的因子,那么n/i也是。但需要注意,当i等于n/i时,不要重复添加。这样可以减少循环次,提高效率。 不过,对于完美的判断来说,可能用户更倾向于简单易懂的实现,而不是最优化的方法,特别是如果用户是初学者的话。所以,可能需要提供一个基础版本和一个优化版本。 然后,用户可能需要生成一定范围内的完美。例如,找出10000以内的所有完美。这时候,可以循环遍历每个,然后调用判断是否为完美的函,收集结果。 另外,需要考虑完美的性质。已知的完美都是偶数,与梅森素有关,但目前是否有奇完美尚未被发现。因此,在代码中可以针对偶数进行处理,但为了全面性,可能还是需要检查所有。 接下来,编写代码。基础版本的函可能如下: def is_perfect(n): if n <= 1: return False sum_divisors = 0 for i in range(1, n): if n % i == 0: sum_divisors += i return sum_divisors == n 然后,生成完美的列表: perfect_numbers = [num for num in range(1, 10001) if is_perfect(num)] 但这种方法在n较大时效率很低,比如检查到10000可能需要较长时间。所以需要考虑优化。 优化后的版本可以减少循环次到sqrt(n),然后收集所有因子。例如: def is_perfect_optimized(n): if n <= 1: return False sum_divisors = 1 # 1是每个的因子 sqrt_n = int(math.sqrt(n)) for i in range(2, sqrt_n + 1): if n % i == 0: sum_divisors += i counterpart = n // i if counterpart != i: sum_divisors += counterpart return sum_divisors == n 但需要注意,这种方法是否正确?比如对于6,sqrt(6)=2,循环从2开始。i=2时,6%2=0,sum加2,counterpart是3,也加入sum。初始sum是1,所以总和是1+2+3=6,正确。所以这个优化方法是可行的。 但是,如果用户输入的n是1,应该返回False。对于n=6,sum_divisors初始化为1,然后i=2时,加2和3,总和是6,正确。所以这个优化后的函是正确的。 所以,在代码中需要导入math模块,并使用math.sqrt函。 接下来,测试这个函是否正确,比如6、28、496等。 此外,用户可能想知道如何生成更多完美,但已知的完美较大,可能需要更高效的算法,比如利用梅森素。但考虑到用户可能需要的是基础的实现方法,这部分可能暂时不需要涉及。 最后,总结步骤,给出代码示例,并说明其原理。同时,在相关问题中,可以引导用户了解其他的判断方法,如质、亲和等,以及如何优化代码性能。</think>### 完美的定义 完美(Perfect Number)是一个正整,其所有真因子(除自身外的因子)之和等于它本身。例如,$6$ 的真因子为 $1, 2, 3$, $1 + 2 + 3 = 6$,因此 $6$ 是完美[^1]。 --- ### 用 Python 完美的步骤 1. **遍历候选**:在定范围内遍历每一个 $n$。 2. **计算真因子和**:找出 $n$ 的所有真因子并和。 3. **判断完美**:若真因子和等于 $n$,则 $n$ 是完美。 --- ### 代码实现 #### 基础版本(直观但效率较低) ```python def is_perfect(n): if n <= 1: return False sum_divisors = 0 for i in range(1, n): if n % i == 0: sum_divisors += i return sum_divisors == n # 找出 10000 以内的完美 perfect_numbers = [num for num in range(1, 10001) if is_perfect(num)] print("完美:", perfect_numbers) # 输出: [6, 28, 496, 8128] ``` #### 优化版本(减少循环次) ```python import math def is_perfect_optimized(n): if n <= 1: return False sum_divisors = 1 # 1 是每个的真因子 sqrt_n = int(math.sqrt(n)) for i in range(2, sqrt_n + 1): if n % i == 0: sum_divisors += i counterpart = n // i if counterpart != i: # 避免重复添加平方根 sum_divisors += counterpart return sum_divisors == n # 测试优化后的函 print(is_perfect_optimized(6)) # True print(is_perfect_optimized(28)) # True ``` --- ### 代码解释 1. **基础版本**:直接遍历 $1$ 到 $n-1$ 的所有,判断是否为因子并和。时间复杂度为 $O(n)$。 2. **优化版本**:遍历到 $\sqrt{n}$,通过因子成对的性质减少循环次。例如,若 $i$ 是 $n$ 的因子,则 $n/i$ 也是因子。时间复杂度优化至 $O(\sqrt{n})$[^2]。 --- ### 注意事项 - 已知的完美均为偶数与梅森素相关(例如 $6 = 2^{2-1}(2^2 - 1)$)[^3]。 - 较大的完美(如 $33550336$)需更高效的算法,例如基于梅森素公式。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值