module Enumerable
def tally(h = {})
each_with_object(h) {|x, h| h[x] = (h[x] || 0) + 1}
end
end
def initial(s, w)
return nil if s < w || w * 5 < s
q, r = (s - w).divmod 4
[w - q - (0 < r ? 1 : 0), 0, 0, 0, q].tap {|b| b[r] = 1 if 0 < r}
end
def next_or_nil(a)
(a.size - 2).downto(0).each_with_object(nil) {|i, _|
next if a[i] == 0
next if not j = (i + 2...a.size).find {|j| a[j] != 0}
return a.dup.tap {|a|
a[i] -= 1; a[i + 1] += 1
a[j] -= 1; a[j - 1] += 1
k = i + 1
s = a[k..-1].each.with_index(k + 1).inject(0) {|s, (c, d)| s + c * d}
w = a[k..-1].sum
w3, r = (s - w * (k + 1)).divmod(5 - (k + 1))
w2 = 0 < r ? 1 : 0
w1 = w - w2 - w3
a.fill(0, k..-1)
a[k] = w1
a[k + r] += w2
a[-1] = w3
}
}
end
def nexts(a)
a && [a].tap {|b| b << a while a = next_or_nil(a)}
end
def f(m, n)
n_permutations = ->a {
factrial = ->n {(1..n).inject(:*) || 1}
factrial.(a.sum) / a.map(&factrial).inject(:*)
}
count_permutations = ->s, w {
nexts(initial(s, w))&.map(&n_permutations)&.sum || 0
}
aux = ->acc, b, s, w {
return acc if s < 1 || w < 1
return acc << s if w == 1
(1..5).inject(b) {|b, d|
c = count_permutations.(s - d, w - 1)
return aux.(acc << d, b, s - d, w - 1) if n <= b + c
b + c
} && nil
}
(1..m).inject(0) {|b, w|
c = count_permutations.(m, w)
return aux.([], b, m, w).join.to_i if n <= b + c
b + c
} && 0
end
g = ->m, n {puts "(#{m},#{n}) → #{f(m, n)}"}
g.(2,1)
g.(2,2)
g.(2,3)
g.(20,1)
g.(20,2)
g.(20,3)
g.(20,400096)
g.(20,400097)
g.(32,1)
g.(32,2)
g.(32,3)
g.(32,1000)
g.(32,1000000)
g.(32,1000000000)
g.(32,1333610936)
g.(32,1333610937)
bW9kdWxlIEVudW1lcmFibGUKICBkZWYgdGFsbHkoaCA9IHt9KQogICAgZWFjaF93aXRoX29iamVjdChoKSB7fHgsIGh8IGhbeF0gPSAoaFt4XSB8fCAwKSArIDF9CiAgZW5kCmVuZApkZWYgaW5pdGlhbChzLCB3KQogIHJldHVybiBuaWwgaWYgcyA8IHcgfHwgdyAqIDUgPCBzCiAgcSwgciA9IChzIC0gdykuZGl2bW9kIDQKICBbdyAtIHEgLSAoMCA8IHIgPyAxIDogMCksIDAsIDAsIDAsIHFdLnRhcCB7fGJ8IGJbcl0gPSAxIGlmIDAgPCByfQplbmQKZGVmIG5leHRfb3JfbmlsKGEpCiAgKGEuc2l6ZSAtIDIpLmRvd250bygwKS5lYWNoX3dpdGhfb2JqZWN0KG5pbCkge3xpLCBffAogICAgbmV4dCBpZiBhW2ldID09IDAKICAgIG5leHQgaWYgbm90IGogPSAoaSArIDIuLi5hLnNpemUpLmZpbmQge3xqfCBhW2pdICE9IDB9CiAgICByZXR1cm4gYS5kdXAudGFwIHt8YXwKICAgICAgYVtpXSAtPSAxOyBhW2kgKyAxXSArPSAxCiAgICAgIGFbal0gLT0gMTsgYVtqIC0gMV0gKz0gMQogICAgICBrID0gaSArIDEKICAgICAgcyA9IGFbay4uLTFdLmVhY2gud2l0aF9pbmRleChrICsgMSkuaW5qZWN0KDApIHt8cywgKGMsIGQpfCBzICsgYyAqIGR9CiAgICAgIHcgPSBhW2suLi0xXS5zdW0KICAgICAgdzMsIHIgPSAocyAtIHcgKiAoayArIDEpKS5kaXZtb2QoNSAtIChrICsgMSkpCiAgICAgIHcyID0gMCA8IHIgPyAxIDogMAogICAgICB3MSA9IHcgLSB3MiAtIHczCiAgICAgIGEuZmlsbCgwLCBrLi4tMSkKICAgICAgYVtrXSA9IHcxCiAgICAgIGFbayArIHJdICs9IHcyCiAgICAgIGFbLTFdID0gdzMKICAgIH0KICB9CmVuZApkZWYgbmV4dHMoYSkKICBhICYmIFthXS50YXAge3xifCBiIDw8IGEgd2hpbGUgYSA9IG5leHRfb3JfbmlsKGEpfQplbmQKZGVmIGYobSwgbikKICBuX3Blcm11dGF0aW9ucyA9IC0+YSB7CiAgICBmYWN0cmlhbCA9IC0+biB7KDEuLm4pLmluamVjdCg6KikgfHwgMX0KICAgIGZhY3RyaWFsLihhLnN1bSkgLyBhLm1hcCgmZmFjdHJpYWwpLmluamVjdCg6KikKICB9CiAgY291bnRfcGVybXV0YXRpb25zID0gLT5zLCB3IHsKICAgIG5leHRzKGluaXRpYWwocywgdykpJi5tYXAoJm5fcGVybXV0YXRpb25zKSYuc3VtIHx8IDAKICB9CiAgYXV4ID0gLT5hY2MsIGIsIHMsIHcgewogICAgcmV0dXJuIGFjYyBpZiBzIDwgMSB8fCB3IDwgMQogICAgcmV0dXJuIGFjYyA8PCBzIGlmIHcgPT0gMQogICAgKDEuLjUpLmluamVjdChiKSB7fGIsIGR8CiAgICAgIGMgPSBjb3VudF9wZXJtdXRhdGlvbnMuKHMgLSBkLCB3IC0gMSkKICAgICAgcmV0dXJuIGF1eC4oYWNjIDw8IGQsIGIsIHMgLSBkLCB3IC0gMSkgaWYgbiA8PSBiICsgYwogICAgICBiICsgYwogICAgfSAmJiBuaWwKICB9CiAgKDEuLm0pLmluamVjdCgwKSB7fGIsIHd8CiAgICBjID0gY291bnRfcGVybXV0YXRpb25zLihtLCB3KQogICAgcmV0dXJuIGF1eC4oW10sIGIsIG0sIHcpLmpvaW4udG9faSBpZiBuIDw9IGIgKyBjCiAgICBiICsgYwogIH0gJiYgMAplbmQKZyA9IC0+bSwgbiB7cHV0cyAiKCN7bX0sI3tufSkg4oaSICN7ZihtLCBuKX0ifQpnLigyLDEpCmcuKDIsMikKZy4oMiwzKQpnLigyMCwxKQpnLigyMCwyKQpnLigyMCwzKQpnLigyMCw0MDAwOTYpCmcuKDIwLDQwMDA5NykKZy4oMzIsMSkKZy4oMzIsMikKZy4oMzIsMykKZy4oMzIsMTAwMCkKZy4oMzIsMTAwMDAwMCkKZy4oMzIsMTAwMDAwMDAwMCkKZy4oMzIsMTMzMzYxMDkzNikKZy4oMzIsMTMzMzYxMDkzNykK