#include #include #include #include using namespace std; using i64 = long long; // {{{ mod_mul, extgcd, mod_inv, mod_pow inline i64 mod_mul(const i64& x, const i64& y, const i64& m) { // yとmの最大ビット長はともに48ビット。 // http://codeforces.com/blog/entry/15884 // 12 < floor(63 - log2(MAX_VALUE)) = 15 // 0xfff = (1<<12) - 1 i64 b, res = y * (x & 0xfff); res += (b=(y<<12) % m) * ((x>>12) & 0xfff); res += (b=(b<<12) % m) * ((x>>24) & 0xfff); res += (b<<12) % m * ((x>>36) & 0xfff); res %= m; return res; } inline tuple extgcd(const i64& x, const i64& y) { if(y == 0) { return {1LL, 0LL, x}; } i64 a, b, d; tie(a, b, d) = extgcd(y, x%y); return {b, a-x/y*b, d}; } inline i64 mod_inv(const i64& a, const i64& m) { i64 x, _, d; tie(x, _, d) = extgcd(a, m); return (x % m + m) % m; } inline i64 mod_pow(const i64& a, const i64& r, const i64& n, const i64& m) { if(n == 0) { return r; } if(n & 1) { return mod_pow(a, mod_mul(a, r, m), n-1, m); } return mod_pow(mod_mul(a, a, m), r, n>>1, m); } inline i64 mod_pow(const i64 a, const i64 n, const i64 m) { return mod_pow(a, 1, n, m); } // }}} struct FMT { static vector convol (const vector& a, const vector& b); static void convol2(vector& a, vector& b); // a に答えが入る。メモリ節約が目的。fftmulで使用。 private: static constexpr i64 N = 5LL << 37; static constexpr i64 O = 2003LL; static constexpr i64 M = N * 211 + 1; static void fmt(vector&); static void ifmt(vector&); static void myfmt(vector&, const bool); }; // {{{ FMT 実装 void FMT::myfmt(vector &a, const bool inv) { const int n = int(a.size()); for(int H=1, W=n>>1; H>=1) { vector y = a; i64 r = mod_pow(O, N/(H*2), M); if(inv) { r = mod_inv(r, M); } i64 w = 1; for(int k=0; k &a) { myfmt(a, false); } void FMT::ifmt(vector &a) { myfmt(a, true); const int n = int(a.size()); i64 inv = mod_inv(n, M); for(int i=0; i FMT::convol(const vector &a, const vector &b) { int n = 1; while(n <= a.size() + b.size()) { n <<= 1; } vector ta = a, tb = b, c(n); ta.resize(n); tb.resize(n); fmt(ta); fmt(tb); for(int i=0; i &a, vector &b) { int n = 1; while(n <= a.size() + b.size()) { n <<= 1; } a.resize(n); b.resize(n); fmt(a); fmt(b); for(int i=0; i a(N); for(int i=0; i c = FMT::convol(a, a); i64 res = 0; if(x < c.size()) { res = c[x]; } printf("%lld\n", res); return 0; }