Problem 26
Reciprocal cycles
A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/2= 0.5
1/3= 0.(3)
1/4= 0.25
1/5= 0.2
1/6= 0.1(6)
1/7= 0.(142857)
1/8= 0.125
1/9= 0.(1)
1/10= 0.1
Where 0.1(6) means 0.166666…, and has a 1-digit recurring cycle. It can be seen that1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
倒数的循环节
单位分数指分子为1的分数。分母为2至10的单位分数的十进制表示如下所示:
1/2= 0.5
1/3= 0.(3)
1/4= 0.25
1/5= 0.2
1/6= 0.1(6)
1/7= 0.(142857)
1/8= 0.125
1/9= 0.(1)
1/10= 0.1
这里0.1(6)表示0.166666…,括号内表示有一位循环节。可以看出,1/7有六位循环节。
找出正整数d < 1000,其倒数的十进制表示小数部分有最长的循环节。
package projecteuler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.Test;
public class Prj26 {
/**
* A unit fraction contains 1 in the numerator. The decimal representation
* of the unit fractions with denominators 2 to 10 are given:
*
* 1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857)
* 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1 Where 0.1(6) means 0.166666..., and
* has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit
* recurring cycle.
*
* Find the value of d < 1000 for which 1/d contains the longest recurring
* cycle in its decimal fraction part.
*/
@Test
public void test() {
Calculator.calculate();
}
public static class Calculator {
public static void calculate() {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 0);
map.put(2, 0);
IntegerDivisor div = new IntegerDivisor();
for(int i = 3; i < 1000; i ++){
div.divisor(i);
long num = getNumExcept2Or5(div.primeMap);
map.put(i, getCycleLen(num));
div.clear();
}
int maxId = 1;
int maxVal = 0;
for( Entry<Integer, Integer> entry : map.entrySet()){
if( entry.getValue() > maxVal){
maxId = entry.getKey();
maxVal = entry.getValue();
}
}
System.out.println("maxId=" + maxId + ", maxVal=" + maxVal);
}
public static long getNumExcept2Or5(Map<Long, Integer> primeMap) {
long val = 1L;
for (Entry<Long, Integer> entry : primeMap.entrySet()) {
if (!entry.getKey().equals(5L) && !entry.getKey().equals(2L)) {
val *= Math.pow(entry.getKey(), entry.getValue());
}
}
return val;
}
public static int getCycleLen(long val) {
if (val == 1L) {
return 0;
}
int count = 1;
int mod = (int) val;
int modVal = 10;
for (;;) {
if (modVal % mod == 1) {
break;
}
modVal = (modVal * 10) % mod;
count++;
}
return count;
}
}
/**
* 因子分解
*
* @author 1440
*
*/
public static class IntegerDivisor {
public Map<Long, Integer> primeMap = new HashMap<Long, Integer>();
public List<Long> primeList = new ArrayList<Long>();
public void clear() {
primeMap.clear();
primeList.clear();
}
public void divisor(long num) {
if (num <= 1)
return;
long prime = getPrime(
num,
primeList.size() == 0 ? 2
: primeList.get(primeList.size() - 1));
if (prime < 0) {
primeMap.put(num, 1);
primeList.add(num);
return;
} else {
primeList.add(prime);
int count = 0;
do {
count += 1;
num = num / prime;
} while (num % prime == 0);
primeMap.put(prime, count);
divisor(num);
}
}
private long getPrime(long num, long start) {
for (long i = start; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
return i;
}
}
return -1;
}
@Override
public String toString() {
return print_Map(this.primeMap);
}
public Long getLargestPrime() {
return primeList.get(primeList.size() - 1);
}
}
public static String print_Map(Map<?, ?> primeMap) {
StringBuilder sb = new StringBuilder();
for (Entry<?, ?> entry : primeMap.entrySet()) {
sb.append(entry.getKey().toString() + "="
+ entry.getValue().toString() + "\n");
}
return sb.toString();
}
public static void print_List(List<Integer> list) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + ",");
}
System.out.println();
}
}