24小时热门版块排行榜    

查看: 2215  |  回复: 16
本帖产生 4 个 程序强帖 ,点击这里进行查看
当前只显示满足指定条件的回帖,点击这里查看本话题的所有回帖

holmescn

金虫 (正式写手)

[交流] Euler 工程 第廿三题: 已有5人参与

完美数是指一个数的所有因子的和还是这个数。比如28=1+2+4+7+14.
如果所有因子的和小于这个数,就称它为“贫数”。反之,如果所有因子的和大于这个数,则称之为“富数”。

比如12是最小的“富数”,因为 1+2+3+4+6=16>12. 最小的可以写为两个“富数”的和的数是24. 由数学分析可知,任何大于28123的整数都可以写成一个两个“富数”的和。但是,这个上限不能继续缩小了,显然已经知道最大的不能写成两个“富数”的和的数要比这个数小。

那么,所有不能写成两个“富数”的和的正整数的和是多少呢?

[ Last edited by holmescn on 2011-6-5 at 23:34 ]
回复此楼

» 猜你喜欢

已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)

★ ★ ★ ★ ★
dubo(金币+1): 多谢交流 2011-06-06 14:43:28
微尘、梦想(金币+4): 2011-06-06 20:17:53
用二分查找代替了线性查找,效率提高了很多。这个版本大概用时30秒
CODE:
# -*- coding: utf-8 -*-

from math import sqrt
from timeit import timeit

def abundantGen():
    "生成一个富数列表"
    abundant = []
    n = 12

    while n < 28123:
        factors = [1]
        sqrtn = int(sqrt(n))
        for i in range(2,sqrtn+1):
            if n % i == 0:
                factors.append(i)
                if n / i != i:
                    factors.append(n/i)

        if sum(factors) > n:
            abundant.append(n)
        n += 1

    return abundant

def find(self, num):
    first = 0
    end = len(self) - 1
    mid = 0

    if len(self) == 0:
        return False

    while first < end:
        if self[mid] == num:
            return True
        mid = (end + first)/2
        if num > self[mid]:
            first = mid + 1
        elif num < self[mid]:
            end = mid - 1

    if first == end and self[first] == num:
        return True
    return False

def euler23():
    # 一个“富数”列表
    abundant = abundantGen()
    n = 1
    s = 0

    while n < 28123:
        flag = True
        for i in abundant:
            if i > n: break
            # 如果n-i在列表内,那么n就可以分成两个
            # “富数”的和
            if find(abundant, n-i):
                flag = False
                break

        if flag:
            s += n

        n += 1

    print s

if __name__ == "__main__":
    print timeit("euler23.euler23()", "import euler23", number=3) / 3

[ Last edited by holmescn on 2011-6-6 at 13:23 ]
7楼2011-06-06 13:07:23
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
查看全部 17 个回答

holmescn

金虫 (正式写手)


dubo(金币+1): 多谢交流 2011-06-06 14:41:22
微尘、梦想(程序强帖+1): 鼓励多交流! 2011-06-06 20:16:22
修改版1
CODE:
# -*- coding: utf-8 -*-

from math import sqrt
from timeit import timeit

def abundantGen():
    "生成一个富数列表"
    abundant = []
    n = 12

    while n < 28123:
        factors = [1]
        sqrtn = int(sqrt(n))
        for i in range(2,sqrtn+1):
            if n % i == 0:
                factors.append(i)
                if n / i != i:
                    factors.append(n/i)

        if sqrtn*sqrtn == n:
            factors.remove(sqrtn)

        if sum(factors) > n:
            abundant.append(n)
        n += 1

    return abundant

def euler23():
    # 一个“富数”列表
    abundant = abundantGen()
    n = 1
    s = 0

    while n < 28123:
        flag = False
        for i in abundant:
            if i > n: break
            try:
                # 如果n-i在列表内,那么n就可以分成两个
                # “富数”的和
                abundant.index(n-i)
                flag = True
                break
            except:
                continue

        if flag == 0:
            s += n

        n += 1

    print s

if __name__ == "__main__":
    print timeit("euler23.euler23()", "import euler23", number=3)

修改以后,结果好像正常了,但时间太长了。
引用回帖:
result = 4179871
takes 1098.32 s

[ Last edited by holmescn on 2011-6-6 at 11:11 ]
2楼2011-06-05 23:40:25
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

libralibra

至尊木虫 (著名写手)

骠骑将军

★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
jjdg(金币+2): 辛苦了 2011-06-06 03:24:33
jjdg(金币+1): 端午节快乐 2011-06-06 03:24:40
微尘、梦想(程序强帖+1): 鼓励多交流! 2011-06-06 20:16:48
你那个富数列表生成判断有问题,不能判断到sqrt(n),必须从1-n-1
例如int(sqrt(12))==3,但是4也整除12;int(sqrt(28))==5,但是14也整除28

这个用matlab速度太慢了,改c了
CODE:
#include
#include

// compute the sum of all factors
int d(int n)
{
        int s=0;
        int i;
        for(i=2;i                 if(n%i==0)
                        s += i;
       
        return s+1; // 加上1
}

// euler23
int main(int args, char* argv[])
{
        int i, j, sum = 0;
        bool flag = false;
        for(i=1;i<28123;i++)
        {
                flag = false;
                for(j=1;j                 {
                        if(j<(i-j)) // j+(i-j)==i,只判断一次
            {
                if(d(j)>j && d(i-j)>(i-j)) // 如果j和i-j都是abundant number,改变flag结束本次循环
                {
                    flag = true;
                    break;
                }
            }               
                }

                if(!flag) // 不能表示为2个abundant number之和
                {
                        sum += i;
                        printf("%d added.\n",i); // 以为死机了,加这句看输出的
                }
        }
       
        printf("\nResult: %d\n",sum); // 打印结果

        system("PAUSE");
        return 0;
}

结果
CODE:
4179871

[ Last edited by libralibra on 2011-6-6 at 01:47 ]
matlab/VB/python/c++/Java写程序请发QQ邮件:790404545@qq.com
3楼2011-06-06 01:43:30
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)


dubo(金币+1): 多谢交流 2011-06-06 14:44:16
引用回帖:
Originally posted by libralibra at 2011-06-06 01:43:30:
你那个富数列表生成判断有问题,不能判断到sqrt(n),必须从1-n-1
例如int(sqrt(12))==3,但是4也整除12;int(sqrt(28))==5,但是14也整除28

这个用matlab速度太慢了,改c了
[code] #include <stdio.h>
#inc ...

我知道你的意思啊,但我有两个append的啊。也就是说

sqrt(12)=3

i 取了 1 2 3
同时
n/i 取了 12 6 4

晕,我说我的和这么小呢, 原来我取了12了
4楼2011-06-06 08:43:16
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
普通表情 高级回复 (可上传附件)
信息提示
请填处理意见