Original

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のPandigital数である (0から9が1度ずつ現れるので). この数は部分語が面白い性質を持っている.

d1を1桁目, d2を2桁目の数とし, 以下順にdnを定義する. この記法を用いると次のことが分かる.

  • d2d3d4=406は2で割り切れる
  • d3d4d5=063は3で割り切れる
  • d4d5d6=635は5で割り切れる
  • d5d6d7=357は7で割り切れる
  • d6d7d8=572は11で割り切れる
  • d7d8d9=728は13で割り切れる
  • d8d9d10=289は17で割り切れる

このような性質をもつ0から9のPandigital数の総和を求めよ.

当てにならないソースコード(C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Collections.Generic;
using System.Linq;

namespace ProjectEuler {
    class Problem43 : Problem{
        List<long> answer = new List<long>();
        Dictionary<long, long> p = new Dictionary<long,long>{
            {17, 13}, {13, 11}, {11,  7},
            { 7,  5}, { 5,  3}, { 3,  2}, { 2,  0},
        };

        public Problem43() {
            for (int i = 0; i < 1000; i++) {
                string s = string.Format("{0:000}", i);
                if (s[0] == s[1] || s[0] == s[2] || s[0] == s[2])
                    continue;
                if (i % 17 == 0) {
                    CheckDiv(s, p[17]);
                }
            }
            Console.WriteLine("> " + answer.Sum());
        }

        void CheckDiv(string before, long div) {
            if (div == 0) {
                string s = before;
                for (int i = 1; i < 10; i++) {
                    string top = i.ToString();
                    if (!before.Contains(top)) {
                        answer.Add(long.Parse(top+before));
                        return;
                    }
                }
                return;// 0から始まる場合はカウントしない
            }
            for (int i = 0; i<10;i++ ) {
                string x = i.ToString();
                if (before.Contains(x))
                    continue;
                long n = i*100 + long.Parse(before.Substring(0,2));
                if (n % div == 0) {
                    CheckDiv(x+before, p[div]);
                }
            }
        }
    }
}


個々の条件については3桁の整数を考えれば良いだけなので簡単です。
しかも条件はパラメータで表せるので1関数で済みます。