完美数

如果一个正整数恰好等于它所有的真因子(即除了自身以外的因子)之和,则称之为完美数(完全数)。
例:6=1+2+3
 

欧几里德完全数定理:若p、(2的p次幂-1) 这两个值均为素数,则 2的(p-1)次幂 乘以 (2的p次幂-1) 的值是个完美数。

利用上面的算法(定理)编程实现求1~10000范围内的完美数如下:

package com.learn.arithmetic;

public class PerfectNumber {

    /**
     * @param args
     */
    public static void main(String[] args) {
        for (long p = 2; p <= 31; p++) {
            if (!pri(p)) {
                continue;
            }
            long t = 2;
            for (int k = 1; k < p; k++) {
                t = t * 2;
            }

            long j = t / 2;
            t--;
            if (pri(t)) {
                System.out.println(j + " * " + t + " = " + (j * t));
            }
        }
        normal();
    }

    // 八个完美数
    // 3 * 2 = 6
    // 7 * 4 = 28
    // 31 * 16 = 496
    // 127 * 64 = 8128
    // 8191 * 4096 = 33550336
    // 131071 * 65536 = 8589869056
    // 524287 * 262144 = 137438691328
    // 2147483647 * 1073741824 = 2305843008139952128

    /**
     * 判断传入的参数是否是一个素数
     *
     * @param suShu
     * @return true=是,false=不是
     */
    public static boolean pri(long suShu) {
        int q = (int) Math.sqrt(suShu) + 1;
        for (int i = 2; i <= q; i++) {
            if (suShu % i == 0 && suShu != 2) {
                return false;
            }
        }
        return true;
    }

    /**
     * 求10000以内的完美数,普通的算法。
     * 找到后,显示成和的形式。
     */
    public static void normal() {
        for (int i = 6; i < 10000; i++) {
            int s = 0;
            for (int j = 1; j <= i / 2; j++) {
                if (i % j == 0) {
                    s += j;
                }
            }

            if (s == i) {
                System.out.print(s + " = 1");
                for (int j = 2; j <= i / 2; j++) {
                    if (i % j == 0) {
                        System.out.print(" + " + j);
                    }
                }
                System.out.println();
            }
        }
    }
}

小结:我们知道,程序=数据结构+算法。

      如果,我们要使得设计的程序显得简洁而高效,那么就需要我们有足够的数学功底和数据结构知识的灵活运用能力。

      例如:求解1~100的自然数之和。

      1)不知道高斯求和公式的程序员会这样编码实现:

      

int i;
int j=100;
int sum=0;
for(i=1;i<=j;i++){
  sum+=i;
}
System.out.println("1~100自然数之和为:"+sum);
      2)掌握了高斯求和算法(公式)的程序员会这样编程实现:

int sum=0;

sum=(1+100)*100/2;

System.out.println("1~100的自然数之和为:"+sum);

由此可知,会算法的程序员比起那些只会硬套(不会或者根本不去使用算法)的程序员要高效许多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值