template<int N, int P>
struct CountSumOfPoints {
constexpr static const long long value = CountSumOfPoints<N - 1, P - 1>::value
+ CountSumOfPoints<N - 1, P - 2>::value
+ CountSumOfPoints<N - 1, P - 3>::value
+ CountSumOfPoints<N - 1, P - 4>::value
+ CountSumOfPoints<N - 1, P - 5>::value
+ CountSumOfPoints<N - 1, P - 6>::value;
};
template<int P>
struct CountSumOfPoints<1, P> {
constexpr static const long long value = 0;
};
template<>
struct CountSumOfPoints<1, 1> {
constexpr static const long long value = 1;
};
template<>
struct CountSumOfPoints<1, 2> {
constexpr static const long long value = 1;
};
template<>
struct CountSumOfPoints<1, 3> {
constexpr static const long long value = 1;
};
template<>
struct CountSumOfPoints<1, 4> {
constexpr static const long long value = 1;
};
template<>
struct CountSumOfPoints<1, 5> {
constexpr static const long long value = 1;
};
template<>
struct CountSumOfPoints<1, 6> {
constexpr static const long long value = 1;
};
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) {
return values[n - N];
}
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() {
//std::cout << CountSumOfPoints<20, 40>::value << std::endl;
//std::cout << CountSumOfPointsTable<20>::value(40) << std::endl;
for (int i = 20; i <= 120; ++i) {
std::cout << CountSumOfPointsTable<20>::value(i) << std::endl;
}
return 0;
}
dGVtcGxhdGU8aW50IE4sIGludCBQPgpzdHJ1Y3QgQ291bnRTdW1PZlBvaW50cyB7CiAgY29uc3RleHByIHN0YXRpYyBjb25zdCBsb25nIGxvbmcgdmFsdWUgPSBDb3VudFN1bU9mUG9pbnRzPE4gLSAxLCBQIC0gMT46OnZhbHVlCiAgICAgICsgQ291bnRTdW1PZlBvaW50czxOIC0gMSwgUCAtIDI+Ojp2YWx1ZQogICAgICArIENvdW50U3VtT2ZQb2ludHM8TiAtIDEsIFAgLSAzPjo6dmFsdWUKICAgICAgKyBDb3VudFN1bU9mUG9pbnRzPE4gLSAxLCBQIC0gND46OnZhbHVlCiAgICAgICsgQ291bnRTdW1PZlBvaW50czxOIC0gMSwgUCAtIDU+Ojp2YWx1ZQogICAgICArIENvdW50U3VtT2ZQb2ludHM8TiAtIDEsIFAgLSA2Pjo6dmFsdWU7Cn07Cgp0ZW1wbGF0ZTxpbnQgUD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgUD4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMDsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgMT4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgMj4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgMz4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgND4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgNT4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IENvdW50U3VtT2ZQb2ludHM8MSwgNj4gewogIGNvbnN0ZXhwciBzdGF0aWMgY29uc3QgbG9uZyBsb25nIHZhbHVlID0gMTsKfTsKCnRlbXBsYXRlPGludC4uLj4Kc3RydWN0IEluZGljZXMgewp9OwoKdGVtcGxhdGU8Y2xhc3MgRnJvbnQsIGludCBCQUNLPiBzdHJ1Y3QgQXBwZW5kOwoKdGVtcGxhdGU8aW50Li4uIEZST05ULCBpbnQgQkFDSz4Kc3RydWN0IEFwcGVuZDxJbmRpY2VzPEZST05ULi4uPiwgQkFDSz4gewogIHR5cGVkZWYgSW5kaWNlczxGUk9OVC4uLiwgQkFDSz4gdHlwZTsKfTsKCnRlbXBsYXRlPGludCBCRUdJTiwgaW50IEVORD4Kc3RydWN0IEluZGV4R2VuZXJhdG9yIHsKICB0eXBlZGVmIHR5cGVuYW1lIEFwcGVuZDx0eXBlbmFtZSBJbmRleEdlbmVyYXRvcjxCRUdJTiwgRU5EIC0gMT46OnR5cGUsIEVORD46OnR5cGUgdHlwZTsKfTsKCnRlbXBsYXRlPGludCBCRUdJTj4Kc3RydWN0IEluZGV4R2VuZXJhdG9yPEJFR0lOLCBCRUdJTj4gewogIHR5cGVkZWYgSW5kaWNlczxCRUdJTj4gdHlwZTsKfTsKCnRlbXBsYXRlPGludCBOPgpzdHJ1Y3QgSW5kZXhMaXN0IHsKICB0eXBlZGVmIHR5cGVuYW1lIEluZGV4R2VuZXJhdG9yPE4sIDYgKiBOPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGU8aW50IE4sIGNsYXNzIEluZGljZXM+IHN0cnVjdCBWYWx1ZXM7Cgp0ZW1wbGF0ZTxpbnQgTiwgaW50Li4uIFA+CmNsYXNzIFZhbHVlczxOLCBJbmRpY2VzPFAuLi4+PiB7CnB1YmxpYzoKICBzdGF0aWMgbG9uZyBsb25nIHZhbHVlKGludCBuKSB7CiAgICByZXR1cm4gdmFsdWVzW24gLSBOXTsKICB9Cgpwcml2YXRlOgogIHN0YXRpYyBjb25zdCBsb25nIGxvbmcgdmFsdWVzW3NpemVvZi4uLihQKV07Cn07Cgp0ZW1wbGF0ZTxpbnQgTiwgaW50Li4uIFA+CmNvbnN0IGxvbmcgbG9uZyBWYWx1ZXM8TiwgSW5kaWNlczxQLi4uPj46OnZhbHVlc1tzaXplb2YuLi4oUCldID0gewogIENvdW50U3VtT2ZQb2ludHM8TiwgUD46OnZhbHVlLi4uCn07Cgp0ZW1wbGF0ZTxpbnQgTj4KdXNpbmcgQ291bnRTdW1PZlBvaW50c1RhYmxlID0gVmFsdWVzPE4sIHR5cGVuYW1lIEluZGV4TGlzdDxOPjo6dHlwZT47CgojaW5jbHVkZSA8aW9zdHJlYW0+CgppbnQgbWFpbigpIHsKICAvL3N0ZDo6Y291dCA8PCBDb3VudFN1bU9mUG9pbnRzPDIwLCA0MD46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICAvL3N0ZDo6Y291dCA8PCBDb3VudFN1bU9mUG9pbnRzVGFibGU8MjA+Ojp2YWx1ZSg0MCkgPDwgc3RkOjplbmRsOwogIGZvciAoaW50IGkgPSAyMDsgaSA8PSAxMjA7ICsraSkgewogICAgc3RkOjpjb3V0IDw8IENvdW50U3VtT2ZQb2ludHNUYWJsZTwyMD46OnZhbHVlKGkpIDw8IHN0ZDo6ZW5kbDsKICB9CiAgcmV0dXJuIDA7Cn0=