numpyを使って競プロの考察を簡単にできないかなあと考えました。
numpyを使って考察を簡単にしたいなあという次第です。
ABC101のD問題Snuke Numbersを使って云々したいと思います。
↓問題
atcoder.jp
とりあえず、すぬけ数の定義を理解するのが難しいです。
簡単に言うと、nより大きい任意の数字mについて、をした時、より小さい値が存在しないということです。
手を動かして実験をしてみるというのが一番簡単なのですがもうちょっと簡単かつグラフなどで可視化できないかなあという感じです。
import numpy as np import matplotlib.pyplot as plt test = 500 x = np.arange(1, test + 1) y = np.array([num/sum(map(int, str(num))) for num in x]) # すぬけ数のインデックスを見つける sunuke_indices = [] for i in range(len(y)): min_num = min(y[i:]) if y[i] == min_num: sunuke_indices.append(i) # グラフを描画 plt.figure(figsize=(10, 6)) plt.plot(x, y, label=r'$\frac{x}{\sum \, \mathrm{digits \, of} \, x}$') plt.scatter(x[sunuke_indices], y[sunuke_indices], color='red', label='Sunuke Numbers') plt.xlabel('x') plt.ylabel(r'$\frac{x}{\sum \, \mathrm{digits \, of} \, x}$') plt.title('Plot of Sunuke Numbers') plt.legend() plt.grid(True) plt.show()
適当に書いてみました。500までの数字でしか比較してませんが、以下のことが分かると思います。
・100の倍数の時、がめちゃくちゃでかくなっている
・上とは逆に、...99みたいな数字の時は小さくなっている
直感的ですが、をなるべく小さくするには、yを最大化させxをなるべく小さくすればいいと考えられます。したがって、についても、S(x)を最大化させるにはとにかく9が多い方が良いんじゃないかなとなります。
この考察は、numpyとmatplotlibを使ってすぬけ数を可視化したおかげに違いないです。
でも本当は単純にコードを書いて直接すぬけ数を求めるのが楽かもしれない...。
参考までに、100000までの数字のすぬけ数を求めたいと思います。
test=10**5 x=list(i for i in range(1,test+1)) y=list(num/sum(list(map(int,list(str(num))))) for num in x) for i in range(len(y)): min_num=min(y[i:]) if y[i]==min_num: print(x[i])
1 2 3 4 5 6 7 8 9 19 29 39 49 59 69 79 89 99 199 299 399 499 599 699 799 899 999 1099 1199 1299 1399 1499 1599 1699 1799 1899 1999 2999 3999 4999 5999 6999 7999 8999 9999 10999 11999 12999 13999 14999 15999 16999 17999 18999 19999 20999 21999 22999 23999 ... ... 100000
ということで、numpyライブラリなどを使って複雑なコードを書いておしゃれに考察をしようとするよりシンプルに考察をした方がいいという結論になりました。
僕はまだ上記の問題を解けていないのでもうちょっと頑張ります。皆さんも頑張ってください。
まとめ
よく見たら今回の考察にnumpyはいらないですね。