#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using uint = unsigned int; using ll = long long; using ull = unsigned long long; template using V = vector; template using VV = V>; constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); } int bsr(int x) { return 31 - __builtin_clz(x); } int bsr(ll x) { return 63 - __builtin_clzll(x); } int bsf(int x) { return __builtin_ctz(x); } int bsf(ll x) { return __builtin_ctzll(x); } template T pow(T x, ll n, T r = 1) { while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } template struct ModInt { uint v; ModInt() : v{0} {} ModInt(ll v) : v{normS(v%MD+MD)} {} explicit operator bool() const {return v != 0;} static uint normS(const uint &x) {return (x string to_string(ModInt m) {return to_string(m.v);} using Mint = ModInt; using R = double; const R PI = 4*atan(R(1)); using Pc = complex; void fft(bool type, vector &c) { static vector buf[30]; int N = int(c.size()); int s = bsr(N); assert(1<(N); for (int i = 0; i < N; i++) { buf[s][i] = polar(1, i*2*PI/N); } } vector a(N), b(N); copy(begin(c), end(c), begin(a)); for (int i = 1; i <= s; i++) { int W = 1<<(s-i); //変更後の幅W for (int y = 0; y < N/2; y += W) { Pc now = buf[s][y]; if (type) now = conj(now); for (int x = 0; x < W; x++) { auto l = a[y<<1 | x]; auto r = now * a[y<<1 | x | W]; b[y | x] = l+r; b[y | x | N>>1] = l-r; } } swap(a, b); } copy(begin(a), end(a), begin(c)); } template vector multiply(vector x, vector y) { int S = x.size()+y.size()-1; int N = 2< a[3], b[3]; for (int fe = 0; fe < 3; fe++) { a[fe] = vector(N); b[fe] = vector(N); for (int i = 0; i < int(x.size()); i++) { a[fe][i] = Pc((x[i].v >> (fe*10)) & ((1<<10)-1), 0); } for (int i = 0; i < int(y.size()); i++) { b[fe][i] = Pc((y[i].v >> (fe*10)) & ((1<<10)-1), 0); } fft(false, a[fe]); fft(false, b[fe]); } vector z(S); vector c(N); Mint base = 1; for (int fe = 0; fe < 5; fe++) { fill_n(begin(c), N, Pc(0, 0)); for (int xf = max(fe-2, 0); xf <= min(2, fe); xf++) { int yf = fe-xf; for (int i = 0; i < N; i++) { c[i] += a[xf][i]*b[yf][i]; } } fft(true, c); for (int i = 0; i < S; i++) { c[i] *= 1.0/N; z[i] += Mint(ll(round(c[i].real()))) * base; } base *= 1<<10; } return z; } template struct Poly { V v; int size() const {return int(v.size());} Poly(int N = 0) : v(V(N)) {} Poly(const V &v) : v(v) {shrink();} Poly& shrink() {while (v.size() && !v.back()) v.pop_back(); return *this;} D freq(int p) const { return (p < size()) ? v[p] : D(0); } Poly operator+(const Poly &r) const { int N = size(), M = r.size(); V res(max(N, M)); for (int i = 0; i < max(N, M); i++) res[i] = freq(i)+r.freq(i); return Poly(res); } Poly operator-(const Poly &r) const { int N = size(), M = r.size(); V res(max(N, M)); for (int i = 0; i < max(N, M); i++) res[i] = freq(i)-r.freq(i); return Poly(res); } Poly operator*(const Poly &r) const { int N = size(), M = r.size(); if (min(N, M) == 0) return Poly(); assert(N+M-1 >= 0); V res = multiply(v, r.v); return Poly(res); } Poly operator*(const D &r) const { V res(size()); for (int i = 0; i < size(); i++) res[i] = v[i]*r; return Poly(res); } Poly& operator+=(const Poly &r) {return *this = *this+r;} Poly& operator-=(const Poly &r) {return *this = *this-r;} Poly& operator*=(const Poly &r) {return *this = *this*r;} Poly& operator*=(const D &r) {return *this = *this*r;} Poly operator<<(const int n) const { assert(n >= 0); V res(size()+n); for (int i = 0; i < size(); i++) { res[i+n] = v[i]; } return Poly(res); } Poly operator>>(const int n) const { assert(n >= 0); if (size() <= n) return Poly(); V res(size()-n); for (int i = n; i < size(); i++) { res[i-n] = v[i]; } return Poly(res); } // x % y Poly rem(const Poly &y) const { return *this - y * div(y); } Poly rem_inv(const Poly &y, const Poly &ny, int B) const { return *this - y * div_inv(ny, B); } Poly div(const Poly &y) const { int B = max(size(), y.size()); return div_inv(y.inv(B), B); } Poly div_inv(const Poly &ny, int B) const { return (*this*ny)>>(B-1); } // this * this.inv() = x^n + r(x) (size()) Poly strip(int n) const { V res = v; res.resize(min(n, size())); return Poly(res); } Poly rev(int n = -1) const { V res = v; if (n != -1) res.resize(n); reverse(begin(res), end(res)); return Poly(res); } // f * f.inv() = x^B + r(x) (B >= n) Poly inv(int n) const { int N = size(); assert(N >= 1); assert(n >= N-1); Poly c = rev(); Poly d = Poly(V({D(1)/c.freq(0)})); int i; for (i = 1; i+N-2 < n; i *= 2) { auto u = V({2}); d = (d * (Poly(V{2})-c*d)).strip(2*i); } return d.rev(n+1-N); } }; template string to_string(const Poly &p) { if (p.size() == 0) return "0"; string s = ""; for (int i = 0; i < p.size(); i++) { if (p.v[i]) { s += to_string(p.v[i])+"x^"+to_string(i); if (i != p.size()-1) s += "+"; } } return s; } // x^n % mod template Poly nth_mod(ll n, const Poly &mod) { int B = mod.size() * 2 - 1; Poly mod_inv = mod.inv(B); Poly p = V{Mint(1)}; int m = (!n) ? -1 : bsr(n); for (int i = m; i >= 0; i--) { if (n & (1LL< pd = {2, 3, 5, 7, 11, 13}; const V cd = {4, 6, 8, 9, 10, 12}; int main() { ll n; int x, y; cin >> n >> x >> y; V co(MD+1); co[0] = 1; { int c = x; Mint buf[MC][MD]; buf[0][0] = 1; for (int d: pd) { for (int nw = MD-1; nw >= 0; nw--) { for (int nc = c; nc >= 0; nc--) { for (int us = 1; us <= nc; us++) { if (nw < d*us) break; buf[nc][nw] += buf[nc-us][nw-d*us]; } } } } V co2(MD+1); for (int i = 0; i < MD; i++) { for (int j = 0; j < MD-i; j++) { co2[i+j] += co[i]*buf[c][j]; } } co = co2; } { int c = y; Mint buf[MC][MD]; buf[0][0] = 1; for (int d: cd) { for (int nw = MD-1; nw >= 0; nw--) { for (int nc = c; nc >= 0; nc--) { for (int us = 1; us <= nc; us++) { if (nw < d*us) break; buf[nc][nw] += buf[nc-us][nw-d*us]; } } } } V co2(MD+1); for (int i = 0; i < MD; i++) { for (int j = 0; j < MD-i; j++) { co2[i+j] += co[i]*buf[c][j]; } } co = co2; } co[0] = -1; auto rco = co; reverse(begin(rco), end(rco)); auto pol = nth_mod(n, Poly(rco)); V buf(MD); buf[0] = 1; V sm(MD); for (int i = 0; i < MD; i++) { //v[i] * f for (int j = 0; j < MD; j++) { sm[j] += pol.freq(i)*buf[j]; } for (int j = 1; j < MD; j++) { buf[j] += buf[0]*co[j]; } for (int j = 0; j < MD-1; j++) { buf[j] = buf[j+1]; } buf[MD-1] = 0; } /* for (int i = 0; i < 10; i++) { cout << sm[i].v << " "; } cout << endl;*/ Mint ans = 0; for (int i = 0; i < MD; i++) { ans += sm[i]; } cout << ans.v << endl; //to_string(Poly(co)) << endl; /* int k, n; cin >> k >> n; n--; Poly md = [&](){ V v(k, Mint(1)); v.push_back(-1); return Poly(v); }(); Poly p = nth_mod(n, md); Mint sm = 0; for (int i = 0; i < k; i++) { sm += p.freq(i); } cout << sm.v << endl;*/ return 0; }