project euler 88

来源:互联网 发布:婴儿面膜淘宝授权书 编辑:程序博客网 时间:2024/06/05 00:52

Problem 88


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,所有最小积和数的和是多少?

package projecteuler;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;import junit.framework.TestCase;public class Prj88 extends TestCase {static final int LIMIT = 12000;static int[] ts = new int[LIMIT];public void testProductSumNumbers() {Set<Integer> set = new HashSet<Integer>();for (int k = 2; k <= LIMIT; k++) {for (int num = k; num <= 2 * k; num++) {if (dfs(0, 2, num, k, num, ts)) {if (k % 1000 == 0) {String fstr = "k=%d,num=%d";fstr = String.format(fstr, k, num);System.out.println(fstr);}set.add(num);break;}}}int sum = 0;for( int val : set){sum += val;}System.out.println("sum=" + sum);}public boolean dfs(int depth, int maxDivisor, int num, int k, int rest,int[] ts) {assert (ts.length == k);// 边界if (depth > k - 1) {return false;}// 检查是否可提前返回if (depth > 0) {int tmp = 0;int mul = 1;for (int i = 0; i < depth; i++) {tmp += ts[i];mul *= ts[i];}assert (ts[depth] <= (num / mul));if (tmp + (k - depth - 1) + num / mul == num) {ts[depth] = num / tmp;printResult(ts, k, depth, num, false);return true;}}List<Integer> divisors = getDivisors(rest, maxDivisor);for (int i = 0; i < divisors.size(); i++) {int div = divisors.get(i);// 保证因子递增且剩下的余积不小于当前最大因子if (rest / div < div) {continue;}ts[depth] = div;if (dfs(depth + 1, div, num, k, rest / div, ts)) {return true;}// no need to reset; a depth flag is enough}return false;}void printResult(int[] idx, int K, int numOfDiv, int num, boolean print) {if (!print) {return;}for (int i = 0; i < idx.length; i++) {if (i != idx.length - 1) {if (i <= numOfDiv) {System.out.print(idx[i] + "+");} else {System.out.print(1 + "+");}} else {if (i <= numOfDiv) {System.out.print(idx[i] + "=");} else {System.out.print(1 + "=");}}}System.out.println(num);}List<Integer> getDivisors(int num, int start) {List<Integer> ret = new ArrayList<Integer>();assert (start <= num);for (int i = start; i < num; i++) {if (num % i == 0) {ret.add(i);}}return ret;}}


0 0