Problem 52
Permuted multiples
It can be seen that the number, 125874, and its double, 251748, contain exactly the same digits, but in a different order.
Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits.
重排的倍数
可以看出,125874和它的两倍251748拥有同样的数字,只是排列顺序不同。
有些正整数x满足2x、3x、4x、5x和6x都拥有相同的数字,求其中最小的正整数。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import junit.framework.TestCase;
public class Prj52 extends TestCase {
/**
* It can be seen that the number, 125874, and its double, 251748, contain
* exactly the same digits, but in a different order.
*
* Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x,
* contain the same digits.
*/
public void test() {
List<int[]> choose = new Comb(9, 6).calculateComb();
List<int[]> allCbs = new Combination(6, 0).generateCom();
for (int[] cb : choose) {
int[] arr = new int[6];
for (int j = 0, k = 0; j < cb.length; j++) {
if (cb[j] == 1) {
arr[k++] = j + 1;
}
}
if (arr[0] != 1) {
continue;
}
Set<Integer> allVals = getAllVals(allCbs, arr);
for (int val : allVals) {
if (allVals.contains(val) && allVals.contains(val * 2)
&& allVals.contains(val * 3)
&& allVals.contains(val * 4)
&& allVals.contains(val * 5)
&& allVals.contains(val * 6)) {
System.out.println("val=" + val);
return;
}
}
}
}
private Set<Integer> getAllVals(List<int[]> allCbs, int[] arr) {
Set<Integer> ret = new HashSet<Integer>();
for (int i = 0; i < allCbs.size(); i++) {
int[] val = new int[arr.length];
int[] id = allCbs.get(i);
for (int j = 0; j < arr.length; j++) {
val[j] = arr[id[j]];
}
ret.add((int) Combination.getIntVal(val));
}
return ret;
}
public static class Combination {
private int[] startArr;
public Combination(int size) {
this(size, 1);
}
public Combination(int size, int startNum) {
startArr = new int[size];
for (int i = 0; i < size; i++) {
startArr[i] = i + startNum;
}
}
public List<int[]> generateCom() {
List<int[]> ret = new ArrayList<int[]>();
ret.add(Arrays.copyOf(startArr, startArr.length));
while (true) {
int lastAsc = findLastAsc(startArr);
if (lastAsc == -1) {
break;
}
int lasBigThanAsc = findBigThanAsc(startArr, lastAsc);
exchangeEach(lastAsc, lasBigThanAsc, startArr);
ret.add(Arrays.copyOf(startArr, startArr.length));
}
return ret;
}
private int findBigThanAsc(int[] startArr2, int lastAsc) {
int i = 0;
for (i = startArr2.length - 1; i > lastAsc; i--) {
if (startArr2[i] > startArr2[lastAsc]) {
return i;
}
}
assert (i > lastAsc);
return i;
}
private void exchangeEach(int lastAsc, int lasBigThanAsc,
int[] startArr2) {
int temp = startArr2[lastAsc];
startArr2[lastAsc] = startArr2[lasBigThanAsc];
startArr2[lasBigThanAsc] = temp;
int[] sortArr = getCopyArr(lastAsc + 1, startArr2);
for (int i = 0; i < sortArr.length / 2; i++) {
temp = sortArr[sortArr.length - 1 - i];
sortArr[sortArr.length - 1 - i] = sortArr[i];
sortArr[i] = temp;
}
for (int i = lastAsc + 1; i < startArr2.length; i++) {
startArr2[i] = sortArr[i - lastAsc - 1];
}
}
private int[] getCopyArr(int start, int[] startArr2) {
int[] ret = new int[startArr2.length - start];
for (int i = start; i < startArr2.length; i++) {
ret[i - start] = startArr2[i];
}
return ret;
}
private int findLastAsc(int[] startArr2) {
for (int i = startArr2.length - 1; i > 0; i--) {
if (startArr2[i] > startArr2[i - 1]) {
return i - 1;
}
}
return -1;
}
public static long getIntVal(int[] arr) {
long sum = arr[0];
for (int i = 1; i < arr.length; i++) {
sum = sum * 10 + arr[i];
}
return sum;
}
}
public static class Comb {
private int n;
private int p;
public Comb(int n, int p) {
this.n = n;
this.p = p;
}
public List<int[]> calculateComb() {
assert (p < n && p > 0);
List<int[]> ret = new ArrayList<int[]>();
int[] arrs = new int[n];
for (int i = 0; i < p; i++) {
arrs[i] = 1;
}
ret.add(Arrays.copyOf(arrs, arrs.length));
for (;;) {
boolean find = findNext(arrs);
ret.add(Arrays.copyOf(arrs, arrs.length));
if (!find) {
break;
}
}
return ret;
}
private boolean findNext(int[] arrs) {
int count = 0;
int find = -1;
for (int i = 0; i < arrs.length - 1; i++) {
if (arrs[i] == 1) {
count++;
}
if (arrs[i] == 1 && arrs[i + 1] == 0) {
int tmp = arrs[i + 1];
arrs[i + 1] = arrs[i];
arrs[i] = tmp;
find = i;
break;
}
}
count--;
for (int i = 0; i < find; i++) {
if (i < count) {
arrs[i] = 1;
} else {
arrs[i] = 0;
}
}
return !(find == -1);
}
}
}