Problem 43
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 2nd digit, and so on. In this way, we note the following:
- d2d3d4=406 is divisible by 2
- d3d4d5=063 is divisible by 3
- d4d5d6=635 is divisible by 5
- d5d6d7=357 is divisible by 7
- d6d7d8=572 is divisible by 11
- d7d8d9=728 is divisible by 13
- d8d9d10=289 is divisible by 17
Find the sum of all 0 to 9 pandigital numbers with this property.
子串的可整除性
1406357289是一个0至9全数字数,因为它由0到9这十个数字排列而成;但除此之外,它还有一个有趣的性质:子串的可整除性。
记d1是它的第一个数字,d2是第二个数字,依此类推,我们注意到:
- d2d3d4=406能被2整除
- d3d4d5=063能被3整除
- d4d5d6=635能被5整除
- d5d6d7=357能被7整除
- d6d7d8=572能被11整除
- d7d8d9=728能被13整除
- d8d9d10=289能被17整除
找出所有满足同样性质的0至9全数字数,并求它们的和。
@Test
public void test() {
Combination comb = new Combination(10, 0);
List<int[]> combinations = comb.generateCom();
long sum = 0;
for (int i = 0; i < combinations.size(); i++) {
int[] arr = combinations.get(i);
if (checkNum(arr, comb)) {
long val = comb.getIntVal(arr);
sum += val;
System.out.println(val);
}
}
System.out.println("sum=" + sum);
}
public boolean checkNum(int[] arr, Combination comb) {
return (comb.getIntVal(Arrays.copyOfRange(arr, 1, 4)) % 2 == 0)
&& (comb.getIntVal(Arrays.copyOfRange(arr, 2, 5)) % 3 == 0)
&& (comb.getIntVal(Arrays.copyOfRange(arr, 3, 6)) % 5 == 0)
&& (comb.getIntVal(Arrays.copyOfRange(arr, 4, 7)) % 7 == 0)
&& (comb.getIntVal(Arrays.copyOfRange(arr, 5, 8)) % 11 == 0)
&& (comb.getIntVal(Arrays.copyOfRange(arr, 6, 9)) % 13 == 0)
&& (comb.getIntVal(Arrays.copyOfRange(arr, 7, 10)) % 17 == 0);
}
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 long getIntVal(int[] arr) {
long sum = arr[0];
for (int i = 1; i < arr.length; i++) {
sum = sum * 10 + arr[i];
}
return sum;
}
}