module Enumerable
def tally(h = {})
each_with_object(h) {|x, h| h[x] = (h[x] || 0) + 1}
end
end
def n_permutations(a)
factrial = ->n {(1..n).inject(:*) || 1}
factrial.(a.size) / a.tally.values.map(&factrial).inject(:*)
end
def next_or_nil(a)
(a.size - 2).downto(0).each_with_object(nil) {|i, _|
next if a[i] == a[i + 1]
next if not j = (i + 1...a.size).find {|j| 2 <= a[j] - a[i]}
return a.dup.tap {|a|
a[i] += 1; a[j] -= 1
w = a.size - j
w3, r = (a[j, w].sum - w * a[i]).divmod(5 - a[i])
w2 = 0 < r ? 1 : 0
w1 = w - w2 - w3
a.fill(a[i], j, w1).fill(a[i] + r, j + w1, w2).fill(5, j + w1 + w2, w3)
}
}
end
def nexts(a)
a && [a].tap {|b| b << a while a = next_or_nil(a)}
end
def initial(s, w)
q, r = (s - w).divmod 4
0 < w && w <= s && s <= w * 5 && (r == 0 || q + 1 <= w) && Array.new(w, 1).tap {|b|
(1..q).each {|i| b[-i] += 4}
b[-q -1] += r if 0 < r
} || nil
end
def f(m, n)
count_permutations = ->s, w {
nexts(initial(s, w))&.map(&method(: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)
bW9kdWxlIEVudW1lcmFibGUKICBkZWYgdGFsbHkoaCA9IHt9KQogICAgZWFjaF93aXRoX29iamVjdChoKSB7fHgsIGh8IGhbeF0gPSAoaFt4XSB8fCAwKSArIDF9CiAgZW5kCmVuZApkZWYgbl9wZXJtdXRhdGlvbnMoYSkKICBmYWN0cmlhbCA9IC0+biB7KDEuLm4pLmluamVjdCg6KikgfHwgMX0KICBmYWN0cmlhbC4oYS5zaXplKSAvIGEudGFsbHkudmFsdWVzLm1hcCgmZmFjdHJpYWwpLmluamVjdCg6KikKZW5kCmRlZiBuZXh0X29yX25pbChhKQogIChhLnNpemUgLSAyKS5kb3dudG8oMCkuZWFjaF93aXRoX29iamVjdChuaWwpIHt8aSwgX3wKICAgIG5leHQgaWYgYVtpXSA9PSBhW2kgKyAxXQogICAgbmV4dCBpZiBub3QgaiA9IChpICsgMS4uLmEuc2l6ZSkuZmluZCB7fGp8IDIgPD0gYVtqXSAtIGFbaV19CiAgICByZXR1cm4gYS5kdXAudGFwIHt8YXwKICAgICAgYVtpXSArPSAxOyBhW2pdIC09IDEKICAgICAgdyA9IGEuc2l6ZSAtIGoKICAgICAgdzMsIHIgPSAoYVtqLCB3XS5zdW0gLSB3ICogYVtpXSkuZGl2bW9kKDUgLSBhW2ldKQogICAgICB3MiA9IDAgPCByID8gMSA6IDAKICAgICAgdzEgPSB3IC0gdzIgLSB3MwogICAgICBhLmZpbGwoYVtpXSwgaiwgdzEpLmZpbGwoYVtpXSArIHIsIGogKyB3MSwgIHcyKS5maWxsKDUsIGogKyB3MSArIHcyLCB3MykKICAgIH0KICB9CmVuZApkZWYgbmV4dHMoYSkKICBhICYmIFthXS50YXAge3xifCBiIDw8IGEgd2hpbGUgYSA9IG5leHRfb3JfbmlsKGEpfQplbmQKZGVmIGluaXRpYWwocywgdykKICBxLCByID0gKHMgLSB3KS5kaXZtb2QgNAogIDAgPCB3ICYmIHcgPD0gcyAmJiBzIDw9IHcgKiA1ICYmIChyID09IDAgfHwgcSArIDEgPD0gdykgJiYgQXJyYXkubmV3KHcsIDEpLnRhcCB7fGJ8CiAgICAoMS4ucSkuZWFjaCB7fGl8IGJbLWldICs9IDR9CiAgICBiWy1xIC0xXSArPSByIGlmIDAgPCByCiAgfSB8fCBuaWwKZW5kCmRlZiBmKG0sIG4pCiAgY291bnRfcGVybXV0YXRpb25zID0gLT5zLCB3IHsKICAgIG5leHRzKGluaXRpYWwocywgdykpJi5tYXAoJm1ldGhvZCg6bl9wZXJtdXRhdGlvbnMpKSYuc3VtIHx8IDAKICB9CiAgYXV4ID0gLT5hY2MsIGIsIHMsIHcgewogICAgcmV0dXJuIGFjYyBpZiBzIDwgMSB8fCB3IDwgMQogICAgcmV0dXJuIGFjYyA8PCBzIGlmIHcgPT0gMQogICAgKDEuLjUpLmluamVjdChiKSB7fGIsIGR8CiAgICAgIGMgPSBjb3VudF9wZXJtdXRhdGlvbnMuKHMgLSBkLCB3IC0gMSkKICAgICAgcmV0dXJuIGF1eC4oYWNjIDw8IGQsIGIsIHMgLSBkLCB3IC0gMSkgaWYgbiA8PSBiICsgYwogICAgICBiICsgYwogICAgfSAmJiBuaWwKICB9CiAgKDEuLm0pLmluamVjdCgwKSB7fGIsIHd8CiAgICBjID0gY291bnRfcGVybXV0YXRpb25zLihtLCB3KQogICAgcmV0dXJuIGF1eC4oW10sIGIsIG0sIHcpLmpvaW4udG9faSBpZiBuIDw9IGIgKyBjCiAgICBiICsgYwogIH0gJiYgMAplbmQKZyA9IC0+bSwgbiB7cHV0cyAiKCN7bX0sI3tufSkg4oaSICN7ZihtLCBuKX0ifQpnLigyLDEpCmcuKDIsMikKZy4oMiwzKQpnLigyMCwxKQpnLigyMCwyKQpnLigyMCwzKQpnLigyMCw0MDAwOTYpCmcuKDIwLDQwMDA5NykKZy4oMzIsMSkKZy4oMzIsMikKZy4oMzIsMykKZy4oMzIsMTAwMCkKZy4oMzIsMTAwMDAwMCkKZy4oMzIsMTAwMDAwMDAwMCkKZy4oMzIsMTMzMzYxMDkzNikKZy4oMzIsMTMzMzYxMDkzNykK