前と同じようなプログラムになると思うと大間違いな場合。
平成 26 年度 京都数学オリンピック道場
10 桁の正の整数の各桁に 0 以上 9 以下のすべての整数が現れ,かつ 11111 の倍数であるとき,その整数を面白い整数と呼ぶことにする。面白い整数は全部でいくつあるか。
今回も「前と同じだ!」と,1 ずつ引いていくと大変なことになるのは目に見えているのに,
function func11()
num = 9876543210
cnt = 0
for i in num:-1:1023456789
if i%11111 == 0 && length(Set(string(i))) == 10
cnt += 1
end
end
print(cnt)
end
@time func11() # 3456 4.728315 seconds
ほらね。言ったとおりでしょ?
1 ずつ引く意味がないのに。
11111 ずつ引きましょう。
function func12()
num = 9876543210 ÷ 11111 * 11111
cnt = 0
for i in num:-11111:1023456789
length(Set(string(i))) == 10 && (cnt += 1)
end
print(cnt)
end
@time func12() # 3456 0.147158 seconds
無駄な引き算を繰り返さないので,30 倍速になりました。
なお,func11() があまりにも遅いので,「0~9 の順列を作って,数字を連結して数を作り,その数が 1000000000 より大きくて,かつ,11111 で割り切れる場合の数を数えよう」として,
using Combinatorics
function func13()
cnt = 0
a = collect(0:9)
j = 0
for i in 1:factorial(length(a))
num = parse(Int, join(nthperm(a, i)))
num > 1000000000 && num % 11111 == 0 && (cnt += 1)
end
println(cnt)
end
を呈示している。しかし,10! = 3628800 通りもの順列の数字を連結したりするのは結構時間がかかる。
しかも,そのうちの 10%(362880個)が 0 で始まる数なのでふるい落とさねばならない。
結局実行時間は
@time func13() # 3456 2.609802 seconds
という情けない結果になってしまう。