いわゆる分割数ではありません。分割して0も認めます。また順番が変わっただけの分割も別とみなします。すなわち、3を3分割なら、
3 = 3 + 0 + 0 = 2 + 1 + 0 = 2 + 0 + 1 = 1 + 2 + 0 = 1 + 1 + 1 = 1 + 0 + 2 = 0 + 3 + 0 = 0 + 2 + 1 = 0 + 1 + 2 = 0 + 0 + 3
全部で10通りあります。
これは母関数を使うと簡単に求められます。まず、1分割はどの整数でも1通りとみなします。各項の係数をその指数の分割の場合の数として、
P1(x) = 1 + x + x2 + x3 + ...
2分割はこの積で求められます。
P2(x) = P1(x)P1(x) = 1 + 2x + 3x2 + 4x3 + ...
例えば、3を分割するとき、3 = 0 + 3 = 1 + 2 = 2 + 1 = 3 + 0ですが、
x0x3 + x1x2 + x2x1 + x3x0
に対応しています。
このようにすると、100の10分割も簡単に求められます。
def mul(f, g): h = [ 0 ] * (N + 1) for k in xrange(N + 1): for l in xrange(N - k + 1): h[k+l] += f[k] * g[l] return h def pow(f, e): if e == 1: return f g = pow(f, e / 2) if e % 2 == 1: return mul(mul(g, g), f) else: return mul(g, g) N = 100 M = 10 f = [ 1 ] * (N + 1) print pow(f, M)[N]
しかし、例えば10000の100分割の場合の数はこのコードではなかなか返ってきません。
このようなときは、Problem 31の方法が使えます。すなわち、n分割のときの母関数の係数は指数のn-1次関数になるので、0〜n-1の分割の場合の数を上の方法で求め、それを用いて母関数の係数の関数の形を求めます。そうすれば10000だろうが1000000だろうが簡単に分割の場合の数を求めることができます。
from itertools import * from fractions import Fraction def mul(f, g): h = [ 0 ] * (M + 1) for k in xrange(M + 1): for l in xrange(M - k + 1): h[k+l] = (h[k+l] + f[k] * g[l]) return h def add(f, g): h = f[:] for k in xrange(M + 1): h[k] += g[k] return h def pow(f, e): if e == 1: return f g = pow(f, e / 2) if e % 2 == 1: return mul(mul(g, g), f) else: return mul(g, g) def unit(): return [ 1 if k == 0 else 0 for k in xrange(M + 1) ] def value(f, x): return reduce(lambda p, q: p * x + q, reversed(f), 0) % D def calc_coeffs(f): def calc_num(k): # numerator g = reduce(mul, imap(lambda l: [ -l, 1 ] + [ 0 ] * (M - 1), ifilter(lambda l: l != k, xrange(M)))) return map(lambda x: x * f[k], g) def calc_den(k): # denominator return reduce(lambda x, l: x * (k - l), ifilter(lambda l: l != k, xrange(M)), 1) def calc_fraction(k): den = calc_den(k) return map(lambda x: Fraction(x, den), calc_num(k)) return reduce(add, imap(calc_fraction, xrange(M))) N = 10000 M = 100 D = 10 ** 8 f = [ 1 ] * (M + 1) fM = pow(f, M) cs = calc_coeffs(fM) print value(cs, N)