template<int N, int P>
struct OutOfBound {
constexpr static const bool value = (P < N) || (P > (6 * N));
};
template<int N, int P, bool OUT_OF_BOUND>
struct CountSumOfPointsImpl {
constexpr static const long long value = 0;
};
template<int N, int P>
struct CountSumOfPointsImpl<N, P, false> {
constexpr static const long long value = CountSumOfPointsImpl<N - 1, P - 1, OutOfBound<N - 1, P - 1>::value>::value
+ CountSumOfPointsImpl<N - 1, P - 2, OutOfBound<N - 1, P - 2>::value>::value
+ CountSumOfPointsImpl<N - 1, P - 3, OutOfBound<N - 1, P - 3>::value>::value
+ CountSumOfPointsImpl<N - 1, P - 4, OutOfBound<N - 1, P - 4>::value>::value
+ CountSumOfPointsImpl<N - 1, P - 5, OutOfBound<N - 1, P - 5>::value>::value
+ CountSumOfPointsImpl<N - 1, P - 6, OutOfBound<N - 1, P - 6>::value>::value;
};
template<int P>
struct CountSumOfPointsImpl<1, P, false> {
constexpr static const long long value = 1;
};
template<int N, int P>
struct CountSumOfPoints {
constexpr static const long long value =
CountSumOfPointsImpl<N, P, OutOfBound<N, P>::value>::value;
};
template<int...>
struct Indices {
};
template<class Front, int BACK> struct Append;
template<int... FRONT, int BACK>
struct Append<Indices<FRONT...>, BACK> {
typedef Indices<FRONT..., BACK> type;
};
template<int BEGIN, int END>
struct IndexGenerator {
typedef typename Append<typename IndexGenerator<BEGIN, END - 1>::type, END>::type type;
};
template<int BEGIN>
struct IndexGenerator<BEGIN, BEGIN> {
typedef Indices<BEGIN> type;
};
template<int N>
struct IndexList {
typedef typename IndexGenerator<N, 6 * N>::type type;
};
template<int N, class Indices> struct Values;
template<int N, int... P>
class Values<N, Indices<P...>> {
public:
static long long value(int n) {
long long val = 0;
if ((n >= N) && (n <= (6 * N))) {
val = values[n - N];
}
return val;
}
private:
static const long long values[sizeof...(P)];
};
template<int N, int... P>
const long long Values<N, Indices<P...>>::values[sizeof...(P)] = {
CountSumOfPoints<N, P>::value...
};
template<int N>
using CountSumOfPointsTable = Values<N, typename IndexList<N>::type>;
#include <iostream>
int main() {
constexpr const int NUM_DICE = 20;
for (int i = NUM_DICE; i <= (6 * NUM_DICE); ++i) {
std::cout << CountSumOfPointsTable<NUM_DICE>::value(i) << std::endl;
}
return 0;
}
dGVtcGxhdGU8aW50IE4sIGludCBQPgpzdHJ1Y3QgT3V0T2ZCb3VuZCB7CiAgY29uc3RleHByIHN0YXRpYyBjb25zdCBib29sIHZhbHVlID0gKFAgPCBOKSB8fCAoUCA+ICg2ICogTikpOwp9OwoKdGVtcGxhdGU8aW50IE4sIGludCBQLCBib29sIE9VVF9PRl9CT1VORD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHNJbXBsIHsKICBjb25zdGV4cHIgc3RhdGljIGNvbnN0IGxvbmcgbG9uZyB2YWx1ZSA9IDA7Cn07Cgp0ZW1wbGF0ZTxpbnQgTiwgaW50IFA+CnN0cnVjdCBDb3VudFN1bU9mUG9pbnRzSW1wbDxOLCBQLCBmYWxzZT4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gQ291bnRTdW1PZlBvaW50c0ltcGw8TiAtIDEsIFAgLSAxLCBPdXRPZkJvdW5kPE4gLSAxLCBQIC0gMT46OnZhbHVlPjo6dmFsdWUKICAgICAgKyBDb3VudFN1bU9mUG9pbnRzSW1wbDxOIC0gMSwgUCAtIDIsIE91dE9mQm91bmQ8TiAtIDEsIFAgLSAyPjo6dmFsdWU+Ojp2YWx1ZQogICAgICArIENvdW50U3VtT2ZQb2ludHNJbXBsPE4gLSAxLCBQIC0gMywgT3V0T2ZCb3VuZDxOIC0gMSwgUCAtIDM+Ojp2YWx1ZT46OnZhbHVlCiAgICAgICsgQ291bnRTdW1PZlBvaW50c0ltcGw8TiAtIDEsIFAgLSA0LCBPdXRPZkJvdW5kPE4gLSAxLCBQIC0gND46OnZhbHVlPjo6dmFsdWUKICAgICAgKyBDb3VudFN1bU9mUG9pbnRzSW1wbDxOIC0gMSwgUCAtIDUsIE91dE9mQm91bmQ8TiAtIDEsIFAgLSA1Pjo6dmFsdWU+Ojp2YWx1ZQogICAgICArIENvdW50U3VtT2ZQb2ludHNJbXBsPE4gLSAxLCBQIC0gNiwgT3V0T2ZCb3VuZDxOIC0gMSwgUCAtIDY+Ojp2YWx1ZT46OnZhbHVlOwp9OwoKdGVtcGxhdGU8aW50IFA+CnN0cnVjdCBDb3VudFN1bU9mUG9pbnRzSW1wbDwxLCBQLCBmYWxzZT4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPGludCBOLCBpbnQgUD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHMgewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0KICAgICAgQ291bnRTdW1PZlBvaW50c0ltcGw8TiwgUCwgT3V0T2ZCb3VuZDxOLCBQPjo6dmFsdWU+Ojp2YWx1ZTsKfTsKCnRlbXBsYXRlPGludC4uLj4Kc3RydWN0IEluZGljZXMgewp9OwoKdGVtcGxhdGU8Y2xhc3MgRnJvbnQsIGludCBCQUNLPiBzdHJ1Y3QgQXBwZW5kOwoKdGVtcGxhdGU8aW50Li4uIEZST05ULCBpbnQgQkFDSz4Kc3RydWN0IEFwcGVuZDxJbmRpY2VzPEZST05ULi4uPiwgQkFDSz4gewogIHR5cGVkZWYgSW5kaWNlczxGUk9OVC4uLiwgQkFDSz4gdHlwZTsKfTsKCnRlbXBsYXRlPGludCBCRUdJTiwgaW50IEVORD4Kc3RydWN0IEluZGV4R2VuZXJhdG9yIHsKICB0eXBlZGVmIHR5cGVuYW1lIEFwcGVuZDx0eXBlbmFtZSBJbmRleEdlbmVyYXRvcjxCRUdJTiwgRU5EIC0gMT46OnR5cGUsIEVORD46OnR5cGUgdHlwZTsKfTsKCnRlbXBsYXRlPGludCBCRUdJTj4Kc3RydWN0IEluZGV4R2VuZXJhdG9yPEJFR0lOLCBCRUdJTj4gewogIHR5cGVkZWYgSW5kaWNlczxCRUdJTj4gdHlwZTsKfTsKCnRlbXBsYXRlPGludCBOPgpzdHJ1Y3QgSW5kZXhMaXN0IHsKICB0eXBlZGVmIHR5cGVuYW1lIEluZGV4R2VuZXJhdG9yPE4sIDYgKiBOPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGU8aW50IE4sIGNsYXNzIEluZGljZXM+IHN0cnVjdCBWYWx1ZXM7Cgp0ZW1wbGF0ZTxpbnQgTiwgaW50Li4uIFA+CmNsYXNzIFZhbHVlczxOLCBJbmRpY2VzPFAuLi4+PiB7CnB1YmxpYzoKICBzdGF0aWMgbG9uZyBsb25nIHZhbHVlKGludCBuKSB7CiAgICBsb25nIGxvbmcgdmFsID0gMDsKICAgIGlmICgobiA+PSBOKSAmJiAobiA8PSAoNiAqIE4pKSkgewogICAgICB2YWwgPSB2YWx1ZXNbbiAtIE5dOwogICAgfQogICAgcmV0dXJuIHZhbDsKICB9Cgpwcml2YXRlOgogIHN0YXRpYyBjb25zdCBsb25nIGxvbmcgdmFsdWVzW3NpemVvZi4uLihQKV07Cn07Cgp0ZW1wbGF0ZTxpbnQgTiwgaW50Li4uIFA+CmNvbnN0IGxvbmcgbG9uZyBWYWx1ZXM8TiwgSW5kaWNlczxQLi4uPj46OnZhbHVlc1tzaXplb2YuLi4oUCldID0gewogIENvdW50U3VtT2ZQb2ludHM8TiwgUD46OnZhbHVlLi4uCn07Cgp0ZW1wbGF0ZTxpbnQgTj4KdXNpbmcgQ291bnRTdW1PZlBvaW50c1RhYmxlID0gVmFsdWVzPE4sIHR5cGVuYW1lIEluZGV4TGlzdDxOPjo6dHlwZT47CgojaW5jbHVkZSA8aW9zdHJlYW0+CgppbnQgbWFpbigpIHsKICBjb25zdGV4cHIgY29uc3QgaW50IE5VTV9ESUNFID0gMjA7CiAgZm9yIChpbnQgaSA9IE5VTV9ESUNFOyBpIDw9ICg2ICogTlVNX0RJQ0UpOyArK2kpIHsKICAgIHN0ZDo6Y291dCA8PCBDb3VudFN1bU9mUG9pbnRzVGFibGU8TlVNX0RJQ0U+Ojp2YWx1ZShpKSA8PCBzdGQ6OmVuZGw7CiAgfQogIHJldHVybiAwOwp9