求完美数

一个数如果恰好等于它的因子之和,这个数就称为"完美数"或"完数"。例如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(子清行
我的CSDN博客(梦婷轩
我的百度空间(梦婷轩

时间: 2024-10-03 09:14:50

求完美数的相关文章

Basic求10000以内的完美数_vb

完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数.它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身. Dim a as Integer,b as Integer,c as Integer For a = 1 To 10000 c = 0 For b = 1 To a \ 2 If a Mod b = 0 Then c = c + b Next b If a = c Then Print Str(a) Next a 另附上java版的代码 im

《数学与泛型编程:高效编程的奥秘》一3.4 完美数

3.4 完美数 正如3.1节所说,古希腊人对数字的各种属性都很感兴趣.他们所提出的一个概念叫做完美数(perfect number),也就是其值等于所有真因子之和的数.古希腊人知道下面这四个完美数: 6 = 1 + 2 + 3 28 = 1 + 2 + 4 + 7 + 14 496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248 8128 = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 127 + 254 + 508 + 1016 + 20

网络营销是一项团队工作 以配合求完美

网络营销是一项团队工作,不是单靠一个两个人就可以完成的工作,因此,网络营销要想搞好,就必须建立一个完整的网络营销体系.那么,如何建立一个完整的网络营销体系,什么样的网络营销体系才算完整? 首先,必须有一个强有力的决定者. 这个决定者可以是一个人,也可以是几个人一个团队.他们的任务是负责对团队策划方案的拍板决定,对团队行动的统一指导.每一个强有力的团队背后都有这么一个英明的决策者,他们要有远见,有谋略,有智慧,见多识广,任何拍脑袋决策都不可以出现在他们手中,所有的决策都必须要经过一些列的反复论证,

UVa 382 Perfection (过剩数、完美数和亏数)

382 - Perfection Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=5&page=show_problem&problem=318 From the article Number Theory in the 1994 Microsoft Encarta: ``If a,b, c are integers

visual studio-VS2015求两数和没法输入数?

问题描述 VS2015求两数和没法输入数? 输入任意键直接退出 没法输入数? 解决方案 cin>>V1>>V2 应该分开 解决方案二: 你单步调试一下,看有没有到最后,或者在main函数退出前加上"system("pause"):",程序就不会退出了. 还有你两个数是怎么输入的,中间是空格么?还是输入一个,回车一下,再输入下一个?

算法-求高数解答二叉树的递归建立问题

问题描述 求高数解答二叉树的递归建立问题 从书上看了一个递归建立二叉树的算法(利用前序遍历建立二叉树).代码如下(这个递归的结束条件是输入一个分号";")但是我不明白的是这个分号是从程序的哪里被读入从而结束递归的. 希望高手解答 #include #include typedef char Type; typedef struct BinTNode{ Type data; struct BinTNode lchild; struct BinTNode *rchild; }BinTNod

二叉树 php-php+mysql求教!!!类似于二叉树求节点数的算法怎么做

问题描述 php+mysql求教!!!类似于二叉树求节点数的算法怎么做 如上图所示,要求的是每一个节点所在的位置下面所有孩子的总数,数字就是数量,下面是我写的程序,不知道错在哪? $sql="select username,prename from {$db_prefix}users where 1 and confirmtime<='$timelimit1' and confirmtime>='$timelimit' and rank>0"; $result=$db

C语言写的求水仙数

C语言写的求水仙数,判断并输出水仙数的部分是在函数里面实现,代码如下:: //本人英文水平不是很好所以就拿中文做注释#include "stdio.h"void is(int a,int b)...{    //定义三个变量作为    int i,j,k;    for(;a<=b;a++)    ...{        i=a%10;//所求数的个位        j=(a/10)%10;//所求数的十位        k=a/100;//所求数的百位        if(i*

写一个完美数程序

完美数,不明白的去bing搜索吧. 下面给程序代码,没有加多线程,不过现在的CPU已经很快了,瞬间就完了. package com.yourcompany.struts; public class PerfectNumber { public static void main(String[] args) { // int sum, k; int perfectNum[] = new int[100]; for (int num = 1; num <= 10000; num++) { int s