project euler 95

来源:互联网 发布:找什么样的老公 知乎 编辑:程序博客网 时间:2024/06/04 19:30

Problem 95


Amicable chains

The proper divisors of a number are all the divisors excluding the number itself. For example, the proper divisors of 28 are 1, 2, 4, 7, and 14. As the sum of these divisors is equal to 28, we call it a perfect number.

Interestingly the sum of the proper divisors of 220 is 284 and the sum of the proper divisors of 284 is 220, forming a chain of two numbers. For this reason, 220 and 284 are called an amicable pair.

Perhaps less well known are longer chains. For example, starting with 12496, we form a chain of five numbers:

12496 → 14288 → 15472 → 14536 → 14264 (→ 12496 → …)

Since this chain returns to its starting point, it is called an amicable chain.

Find the smallest member of the longest amicable chain with no element exceeding one million.


亲和数链

一个数除了本身之外的因数称为真因数。例如,28的真因数是1、2、4、7和14。这些真因数的和恰好为28,因此我们称28是完全数。

有趣的是,220的真因数之和是284,同时284的真因数之和是220,构成了一个长度为2的链,我们也称之为亲和数对。

有一些更长的序列并不太为人所知。例如,从12496出发,可以构成一个长度为5的链:

12496 → 14288 → 15472 → 14536 → 14264 (→ 12496 → …)

由于这条链最后又回到了起点,我们称之为亲和数链。

找出所有元素都不超过一百万的亲和数链中最长的那条,并给出其中最小的那个数。

package projecteuler;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import junit.framework.TestCase;public class Prj95 extends TestCase {private static final int LIMIT = 1000000;public static Map<Integer, List<Integer>> AMICABLE_CHAINS = new HashMap<Integer, List<Integer>>();public void testAmicableChains() {MyBitSet bt = new MyBitSet(LIMIT);bt.set(0);bt.set(1);bt.set(2);bt.set(3);bt.set(4);bt.set(5);int start = 5;int count = 0 ;while (true) {start = bt.nextClearBit(start);if( (count ++) % 1000 == 0){System.out.println("start=" + start);}if (isPrime(start)) {bt.set(start);start = bt.nextClearBit(start);continue;}List<Integer> dataList = new ArrayList<Integer>();dataList.add(start);int next = start;boolean breakNotAmicable = false;boolean breakFindCycle = false;while (true) {next = sumDivisors(getDivisors(next));if (start == next) {break;}if (next == 1 || next > LIMIT || bt.get(next)) {breakNotAmicable = true;break;}if (dataList.contains(next) && next != start) {breakFindCycle = true;break;}//System.out.println(next);dataList.add(next);}if (breakFindCycle) {int id = dataList.indexOf(next);List<Integer> tmp = new ArrayList<Integer>();for (int i = id; i < dataList.size(); i++) {tmp.add(dataList.get(i));}int min = Collections.min(tmp);AMICABLE_CHAINS.put(min, tmp);}else if (!breakNotAmicable) {if (AMICABLE_CHAINS.containsKey(dataList.get(0))) {throw new RuntimeException(" AMICABLE_CHAINS.containsKey("+ start + ")");}int min = Collections.min(dataList);AMICABLE_CHAINS.put(min, dataList);}for (int i = 0; i < dataList.size(); i++) {int id_ = dataList.get(i);bt.set(id_);}start = bt.nextClearBit(start);if (start > LIMIT) {break;}}System.out.println(AMICABLE_CHAINS);int max = 0;int key = 0;for( Entry<Integer, List<Integer>> entry : AMICABLE_CHAINS.entrySet()){if( entry.getValue().size() > max){max = entry.getValue().size();key = entry.getKey();}}System.out.println("key=" + key  + ",value=" + AMICABLE_CHAINS.get(key));}private int sumDivisors(List<Integer> divisors) {int sum = 0;for (int i = 0; i < divisors.size(); i++) {sum += divisors.get(i);}return sum;}List<Integer> getDivisors(int num) {List<Integer> ret = new ArrayList<Integer>();for (int i = 1; i < num; i++) {if (num % i == 0) {ret.add(i);}}return ret;}boolean isPrime(int val) {if (val <= 10) {if (val == 2 || val == 3 || val == 5 || val == 7) {return true;}return false;}if (val % 2 == 0) {return false;}for (int i = 3; i * i <= val; i = i + 2) {if (val % i == 0) {return false;}}return true;}public static class MyBitSet{private int[] bits;public MyBitSet(int n ){this.bits = new int[n + 1];}public boolean get(int next) {return bits[next] == 1;}public int nextClearBit(int start){for(int i = start; i < bits.length; i ++){if( bits[i] == 0){return i;}}return bits.length + 1;}public void set(int id){if( id < bits.length){bits[id] = 1; }}}}


0 0