Project Euler 88:Product-sum numbers 积和数

Product-sum numbers

A natural number, N, that can be written as the sum and product of a given set of at least two natural numbers, {a1, a2, … , ak} is called a product-sum number: N = a1 + a2 + … + ak = a1 × a2 × … × ak.

For example, 6 = 1 + 2 + 3 = 1 × 2 × 3.

For a given set of size, k, we shall call the smallest N with this property a minimal product-sum number. The minimal product-sum numbers for sets of size, k = 2, 3, 4, 5, and 6 are as follows.

k=2: 4 = 2 × 2 = 2 + 2
k=3: 6 = 1 × 2 × 3 = 1 + 2 + 3
k=4: 8 = 1 × 1 × 2 × 4 = 1 + 1 + 2 + 4
k=5: 8 = 1 × 1 × 2 × 2 × 2 = 1 + 1 + 2 + 2 + 2
k=6: 12 = 1 × 1 × 1 × 1 × 2 × 6 = 1 + 1 + 1 + 1 + 2 + 6

Hence for 2≤k≤6, the sum of all the minimal product-sum numbers is 4+6+8+12 = 30; note that 8 is only counted once in the sum.

In fact, as the complete set of minimal product-sum numbers for 2≤k≤12 is {4, 6, 8, 12, 15, 16}, the sum is 61.

What is the sum of all the minimal product-sum numbers for 2≤k≤12000?



积和数

若自然数N能够同时表示成一组至少两个自然数{a1, a2, … , ak}的积和和,也即N = a1 + a2 + … + ak = a1 × a2 × … × ak,则N被称为积和数。

例如,6是积和数,因为6 = 1 + 2 + 3 = 1 × 2 × 3。

给定集合的规模k,我们称满足上述性质的最小N值为最小积和数。当k = 2、3、4、5、6时,最小积和数如下所示:

k=2: 4 = 2 × 2 = 2 + 2
k=3: 6 = 1 × 2 × 3 = 1 + 2 + 3
k=4: 8 = 1 × 1 × 2 × 4 = 1 + 1 + 2 + 4
k=5: 8 = 1 × 1 × 2 × 2 × 2 = 1 + 1 + 2 + 2 + 2
k=6: 12 = 1 × 1 × 1 × 1 × 2 × 6 = 1 + 1 + 1 + 1 + 2 + 6

因此,对于2≤k≤6,所有的最小积和数的和为4+6+8+12 = 30;注意8只被计算了一次。

已知对于2≤k≤12,所有最小积和数构成的集合是{4, 6, 8, 12, 15, 16},这些数的和是61。

对于2≤k≤12000,所有最小积和数的和是多少?

解题

k个数的和 == k个数的积

求对应k时候最小的这个数

题目要求2≤k≤12000,时候的最小积数和的和

参考题解中的程序,详解程序注释

Java

package Level3;

import java.util.Set;
import java.util.TreeSet;

public class PE088{
    static void run(){
        int Kmin = 2;
        int Kmax = 12000;
        int sum = 0;
        Set<Integer> set = new TreeSet<Integer>();
        for(int k=Kmin;k<=Kmax;k++){
            int minN = getMin(k);
            if(set.add(minN))
                sum+=minN;
        }
        System.out.println(sum);
    }
    // 找出k对于最小的n
    static int getMin(int k){
        for(int n=k+1;;n++){
            if(check(n,n,k))
                return n;
        }
    }
    // 一个数拆成成k个数的和或者k个数的积
    // prod 乘
    // sum 和
    // 开始的时候这两个数是相等的  都是 prod 或者sum 拆分成k份 

//    这里用到的是递归的方法,当 prod2 = prod1 * a ;sum2 = sum1- a
//            下面就可以检测下一轮了 check(prod2,sum2,k-1)
//    这里用递归也是因为可能出  8 = 2*2*2*1*1 = 2+2+2+1+1  的形式,乘子中有数相同 的情况
//    结束情况: 乘子是1的时候  sum == k k个1的和就是sum了
//     k=1的时候  说明结束了 return prod == sum
//    下次递归可进行需要:d<= prod  k-1<= sum-d 下面程序很显然的
    static boolean check(int prod,int sum,int k){
        if(sum <k) return false;
        if(prod == 1) return sum==k;
        if(k==1) return prod ==sum;
        for(int d =2;d<= prod && sum-d>=k-1;d++){
            if(prod%d==0){
                if(check(prod/d,sum-d,k-1))
                    return true;
            }
        }
        return false;
    }
//    7587457
//    running time=1s577ms
    public static void main(String[] args){
        long t0 = System.currentTimeMillis();
        run();
        long t1 = System.currentTimeMillis();
        long t = t1 - t0;
        System.out.println("running time="+t/1000+"s"+t%1000+"ms");

    }
}

参考链接

n[k]表示minimal product-sum numbers for size=k

n[k]的上界为2*k,因为2*k总是能分解成2*k,然后2*k=k+2+(1)*(k-2)

显然n[k]的下界为k

对于一个数num   因式分解后因子个数为product   这些因子的和为sump

则需要添加的1的个数为num-sump,所以size k=num-sump+product

===============================================

上面说的很好理解

在对于因式分解中

n[k] 是 一个数分解成k个数的和  、k个数的积的最小值

我上面链接中的程序的理解是通过因式分解,不断的缩小n[k]处的值,最终的值就是最小的,但是程序后面的递归理解不透。。。

# coding=gbk

import time as time
def run2():
    kMax = 12000
    n = [2*kMax for i in range(kMax)]

    def getpsn(num,sump,product,start):
        k = num - sump + product
        if k < kMax:
            if num<n[k]:
                n[k] = num
            for i in range(start,kMax//num *2):
                getpsn(num*i,sump+i,product + 1,i)
    getpsn(1,1,1,2)
    ans = sum(set(n[2:]))
    print ans
# 7587457
# running time= 0.266000032425 s
def run():
    kMin = 2
    kMax = 12000
    res=[]
    for k in range(kMin,kMax+1):
        minN = getMinN(k)
        if minN not in res:
            res.append(minN)
    print sum(minN)

def getMinN(k):
    n = k + 1
    while(True):
        if check(n,n,k):
            return n
        n +=1

def check(prod,sum,k):
    if sum<k : return False
    if prod == 1:return sum==k
    if k==1 :return prod ==sum
    for d in range(2,prod):
        if sum-d>=k-1 and prod%d ==0:
            if check(prod/d,sum-d,k-1):
                return True
    return False

t0 = time.time()
run2()
t1 = time.time()
print "running time=",(t1-t0),"s"
时间: 2024-10-27 13:24:54

Project Euler 88:Product-sum numbers 积和数的相关文章

Project Euler——13.Larger Sum总结

今天花了一天的时间在Linux 系统上完成了欧拉计划第13题的Larger Sum编程(花费的时间有点长啊).既然耗了这么长的时间,那就要好好的总结一下,不然也对不起这一天的时间.这次主要是在ubantu 上编程,简单的设计到了编译.调试.链接和简单的编写Makefile. Larger Sum 中涉及到了超大数(50位)的计算,在C编译语言中,int 为32位,最大的整数long long int也只有pow(2,64)大约19位,这样完全不能用简单的四和运算来求和.于是代码中,我使用字符串的

project euler之Large sum

import fileinput f=open("1.txt","r") m=0 for i in range(100): s=f.readline() m+=int(s) print(m) 原文地址:https://www.cnblogs.com/chif/p/9280837.html

Python练习题 048:Project Euler 021:10000以内所有亲和数之和

本题来自 Project Euler 第21题:https://projecteuler.net/problem=21 ''' Project Euler: Problem 21: Amicable numbers Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). If d(a) = b and d(b) = a, where a ≠ b

Python练习题 034:Project Euler 006:和平方与平方和之差

本题来自 Project Euler 第6题:https://projecteuler.net/problem=6 # Project Euler: Problem 6: Sum square difference # The sum of the squares of the first ten natural numbers is, # 1**2 + 2**2 + ... + 10**2 = 385 # The square of the sum of the first ten natur

Project Euler 第一题效率分析

Project Euler: 欧拉计划是一系列挑战数学或者计算机编程问题,解决这些问题需要的不仅仅是数学功底. 启动这一项目的目的在于,为乐于探索的人提供一个钻研其他领域并且学习新知识的平台,将这一平台打造一个有趣和休闲 的环境. 项目主页:https://projecteuler.net 第一题 Multiples of 3 and 5 If we list all the natural numbers below 10 that are multiples of 3 or 5, we ge

Python练习题 041:Project Euler 013:求和、取前10位数值

本题来自 Project Euler 第13题:https://projecteuler.net/problem=13 # Project Euler: Problem 13: Large sum # Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. # Answer: 5537376230 numbers = '''371072875339021027987979982

Python练习题 037:Project Euler 009:毕达哥拉斯三元组之乘积

本题来自 Project Euler 第9题:https://projecteuler.net/problem=9 # Project Euler: Problem 9: Special Pythagorean triplet # A Pythagorean triplet is a set of three natural numbers, # a < b < c, for which, a**2 + b**2 = c**2 # For example, 3**2 + 4**2 = 9 +

[Perl 6][Project Euler] Problem 9 - Special Pythagorean triplet

[Perl 6][Project Euler] Problem 9 - Special Pythagorean triplet Description A Pythagorean triplet is a set of three natural numbers, a < b < c, for which, a^2 + b^2 = c^2 For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2. There exists exactly one Pythagore

Problem 43 // Project Euler

Sub-string divisibility The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property. Let d1 be the 1st digit, d2 be the