プロジェクトオイラー
http://projecteuler.net/index.php
Q169.
1025を2のべきで分割する方法の個数。ただし、1もOK、同じ数は2つまで。
普通に、再帰で書ける。大きい数から使っていき、それがあと何回使えるかで関数にする。2m以下しか使えないとき、2m+2-2までにしかならないので、それでかなり絞り込める。また、まともに再帰だと時間がかかるので、一度計算した結果は辞書に入れておく。
def g(n, m, k):
if n == 1:
return 1
elif m == 0:
if n == 2 and k == 2:
return 1
else:
return 0
if (n, m, k) in g_dic:
return g_dic[(n,m,k)]
s = 0
for e in range(m, -1, -1):
if e == m and k == 1:
if (1 << e) * 3 < n + 2:
break
else:
if 1 << e + 2 < n + 2:
break
p = 1 << e
if p == n:
s += 1
elif p < n:
if e == m and k == 1:
s += g(n - p, e - 1, 2)
else:
s += g(n - p, e, 1)
g_dic[(n,m,k)] = s
return sdef f(n):
e = 0
while n >> e:
e += 1
return g(n, e - 1, 2)g_dic = { }
N = 10 ** 25
print f(N)