#include using namespace std; using ll = long long; using u32 = uint32_t; using u64 = uint64_t; // for文の短縮マクロ #define rep0(i, n) for (int i = 0; i < (int)(n); ++i) #define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++) #define rrep(i, a, b) for (int i = (int)(a); i > (int)(b); --i) #define srep(i, a, b, step) \ for (long long i = (a); (step) > 0 ? i < (b) : i > (b); i += (step)) // コンテナ操作の短縮マクロ #define all(v) (v).begin(), (v).end() #define MIN(v) *min_element(all(v)) #define MAX(v) *max_element(all(v)) // よく使う定数 const int INF = (1 << 30); const ll INFLL = (1LL << 62); const ll MOD = 998244353; const ll MOD2 = 1000000007; // 型ごとにread/printを拡張した入出力ヘルパー namespace fastio { // 入力 template void read(T &x) { cin >> x; } template void read(pair &p) { read(p.first); read(p.second); } template inline enable_if_t read_tuple(tuple &) {} template inline enable_if_t < I read_tuple(tuple &t) { read(get(t)); read_tuple(t); } template void read(tuple &t) { read_tuple(t); } template void read(array &a) { for (auto &x : a) read(x); } template void read(vector &v) { for (auto &x : v) read(x); } template void read(deque &v) { for (auto &x : v) read(x); } template void read(Head &head, Tail &...tail) { read(head); if constexpr (sizeof...(Tail)) read(tail...); } // 基本型 template void wt(const T &x) { cout << x; } // 小数は小数点以下10桁で固定出力 inline void wt(float x) { cout << fixed << setprecision(10) << x; } inline void wt(double x) { cout << fixed << setprecision(10) << x; } inline void wt(long double x) { cout << fixed << setprecision(10) << x; } // 文字列系 inline void wt(const char *s) { cout << s; } inline void wt(const string &s) { cout << s; } // pair template void wt(const pair &p) { wt(p.first); cout << ' '; wt(p.second); } // tuple template inline enable_if_t wt_tuple(const tuple &) {} template inline enable_if_t < I wt_tuple(const tuple &t) { if (I) cout << ' '; wt(get(t)); wt_tuple(t); } template void wt(const tuple &t) { wt_tuple(t); } // コンテナ内要素を再帰的に出力するための前方宣言 template void wt(const set &s); template void wt(const multiset &s); template void wt(const unordered_set &s); template void wt(const map &m); template void wt(const unordered_map &m); template void wt(const priority_queue &q); // array / vector / deque template void wt(const array &a) { for (size_t i = 0; i < N; i++) { if (i) cout << ' '; wt(a[i]); } } template void wt(const vector &v) { for (size_t i = 0; i < v.size(); i++) { if (i) cout << ' '; wt(v[i]); } } template void wt(const vector> &v) { for (size_t i = 0; i < v.size(); i++) { if (i) cout << '\n'; wt(v[i]); } } template void wt(const deque &v) { for (size_t i = 0; i < v.size(); i++) { if (i) cout << ' '; wt(v[i]); } } template void wt(const priority_queue &q) { auto qq = q; bool first = true; while (!qq.empty()) { if (!first) cout << ' '; first = false; wt(qq.top()); qq.pop(); } } // set / multiset / unordered_set template void wt(const set &s) { bool first = true; for (auto &x : s) { if (!first) cout << ' '; first = false; wt(x); } } template void wt(const multiset &s) { bool first = true; for (auto &x : s) { if (!first) cout << ' '; first = false; wt(x); } } template void wt(const unordered_set &s) { bool first = true; for (auto &x : s) { if (!first) cout << ' '; first = false; wt(x); } } // map / unordered_map template void wt(const map &m) { bool first = true; for (auto &kv : m) { if (!first) cout << " | "; first = false; wt(kv.first); cout << ':'; wt(kv.second); } } template void wt(const unordered_map &m) { bool first = true; for (auto &kv : m) { if (!first) cout << " | "; first = false; wt(kv.first); cout << ':'; wt(kv.second); } } // 出力本体 void print() { cout << '\n'; } template void print(const Head &head, const Tail &...tail) { wt(head); if (sizeof...(Tail)) cout << ' '; print(tail...); } } // namespace fastio // 頻出のI/O関数だけ名前空間から取り出す using fastio::print; using fastio::read; // 宣言+入力を1行で書くマクロ #define INT(...) \ int __VA_ARGS__; \ read(__VA_ARGS__) #define LL(...) \ ll __VA_ARGS__; \ read(__VA_ARGS__) #define U32(...) \ u32 __VA_ARGS__; \ read(__VA_ARGS__) #define U64(...) \ u64 __VA_ARGS__; \ read(__VA_ARGS__) #define STR(...) \ string __VA_ARGS__; \ read(__VA_ARGS__) #define CHAR(...) \ char __VA_ARGS__; \ read(__VA_ARGS__) #define DBL(...) \ double __VA_ARGS__; \ read(__VA_ARGS__) #define VEC(type, name, size) \ vector name(size); \ read(name) #define VV(type, name, h, w) \ vector> name(h, vector(w)); \ read(name) #define VEC0(type, name, size) \ vector name(size) #define VV0(type, name, h, w) \ vector> name(h, vector(w)) #define VECI(type, name, size, init) \ vector name(size, init) #define VVI(type, name, h, w, init) \ vector> name(h, vector(w, init)) // orderedコンテナ(set/multiset等)の境界検索ヘルパー // GE_IT(c, x): x以上の最小要素のiterator // LE_IT(c, x): x以下の最大要素のiterator(なければend) template auto ge_it(const C &c, const T &x) { return c.lower_bound(x); } template auto le_it(const C &c, const T &x) { auto it = c.upper_bound(x); if (it == c.begin()) return c.end(); --it; return it; } template typename C::value_type ge_val(const C &c, const T &x) { auto it = ge_it(c, x); if (it == c.end()) throw out_of_range("GE_VAL: no element >= x"); return *it; } template typename C::value_type le_val(const C &c, const T &x) { auto it = le_it(c, x); if (it == c.end()) throw out_of_range("LE_VAL: no element <= x"); return *it; } template bool discard_one(set &s, const T &x) { return s.erase(x) > 0; } template bool discard_one(multiset &s, const T &x) { auto it = s.find(x); if (it == s.end()) return false; s.erase(it); // erase only one return true; } template int discard_all(set &s, const T &x) { return (int)s.erase(x); // 0 or 1 } template int discard_all(multiset &s, const T &x) { return (int)s.erase(x); // remove all x } #define GE_IT(c, x) ge_it((c), (x)) #define LE_IT(c, x) le_it((c), (x)) #define GE_VAL(c, x) ge_val((c), (x)) #define LE_VAL(c, x) le_val((c), (x)) #define DISCARD_ONE(c, x) discard_one((c), (x)) #define DISCARD_ALL(c, x) discard_all((c), (x)) // std::setでPython風の集合演算を使うための演算子オーバーロード // A | B, A & B, A - B, A ^ B と代入版 template set operator|(const set &a, const set &b) { set res(a.begin(), a.end(), a.key_comp(), a.get_allocator()); res.insert(b.begin(), b.end()); return res; } template set operator&(const set &a, const set &b) { set res(a.key_comp(), a.get_allocator()); for (const auto &x : a) { if (b.contains(x)) res.insert(x); } return res; } template set operator-(const set &a, const set &b) { set res(a.key_comp(), a.get_allocator()); for (const auto &x : a) { if (!b.contains(x)) res.insert(x); } return res; } template set operator^(const set &a, const set &b) { set res = a - b; for (const auto &x : b) { if (!a.contains(x)) res.insert(x); } return res; } template set &operator|=(set &a, const set &b) { a = a | b; return a; } template set &operator&=(set &a, const set &b) { a = a & b; return a; } template set &operator-=(set &a, const set &b) { a = a - b; return a; } template set &operator^=(set &a, const set &b) { a = a ^ b; return a; } template bool is_subset(const set &a, const set &b) { for (const auto &x : a) { if (!b.contains(x)) return false; } return true; } template bool is_superset(const set &a, const set &b) { return is_subset(b, a); } template bool is_disjoint(const set &a, const set &b) { for (const auto &x : a) { if (b.contains(x)) return false; } return true; } // 二分探索ヘルパー(Pythonのbisect相当) template int bisect_left(const vector &v, const T &x) { return int(lower_bound(v.begin(), v.end(), x) - v.begin()); } template int bisect_right(const vector &v, const T &x) { return int(upper_bound(v.begin(), v.end(), x) - v.begin()); } // 整数累乗(繰り返し二乗法) long long ipow(long long a, long long e) { long long r = 1; while (e > 0) { if (e & 1) r *= a; a *= a; e >>= 1; } return r; } // 区切り文字付きjoinヘルパー template string join(It first, It last, const string &sep) { ostringstream oss; bool first_elem = true; for (auto it = first; it != last; ++it) { if (!first_elem) oss << sep; first_elem = false; oss << *it; } return oss.str(); } inline string join(const vector &v, const string &sep) { size_t total = 0; if (!v.empty()) total = (v.size() - 1) * sep.size(); for (const auto &s : v) total += s.size(); string res; res.reserve(total); for (size_t i = 0; i < v.size(); ++i) { if (i) res += sep; res += v[i]; } return res; } inline string join(const string &s, const string &sep) { if (s.empty()) return ""; string res; if (!sep.empty()) res.reserve(s.size() + (s.size() - 1) * sep.size()); for (size_t i = 0; i < s.size(); ++i) { if (i) res += sep; res += s[i]; } return res; } template string join(const C &c, const string &sep) { return join(c.begin(), c.end(), sep); } // 便利ユーティリティ(反転・合計・連結) template C reversed(C c) { reverse(c.begin(), c.end()); return c; } template long long sum(const vector &v) { return accumulate(v.begin(), v.end(), 0LL); } template vector concat(const vector &a, const vector &b) { vector res; res.reserve(a.size() + b.size()); res.insert(res.end(), a.begin(), a.end()); res.insert(res.end(), b.begin(), b.end()); return res; } template vector operator+(const vector &a, const vector &b) { return concat(a, b); } template vector &operator+=(vector &a, const vector &b) { a.insert(a.end(), b.begin(), b.end()); return a; } template array concat(const array &a, const array &b) { array res{}; copy(a.begin(), a.end(), res.begin()); copy(b.begin(), b.end(), res.begin() + N); return res; } // 隣接リスト形式の軽量グラフ struct Graph { int n; vector> g; Graph(int n = 0) : n(n), g(n) {} void add_edge(int u, int v, bool undirected = true) { g[u].push_back(v); if (undirected) g[v].push_back(u); } vector &operator[](int i) { return g[i]; } const vector &operator[](int i) const { return g[i]; } }; // ===== BEGIN MODINT COPY BLOCK ===== // Copy and paste from this line to the END marker below. #ifndef MODINT_LIBRARY_MODINT_HPP #define MODINT_LIBRARY_MODINT_HPP 1 #include #include #include #ifdef _MSC_VER #include #endif namespace modint_lib { namespace internal { struct modint_base { }; struct static_modint_base : modint_base { }; template using is_modint = std::is_base_of; template using is_modint_t = std::enable_if_t::value>; template using is_signed_int_t = std::enable_if_t::value && std::is_signed::value>; template using is_unsigned_int_t = std::enable_if_t::value && std::is_unsigned::value>; constexpr long long safe_mod(long long x, long long m) { x %= m; if (x < 0) x += m; return x; } constexpr long long pow_mod_constexpr(long long x, long long n, int m) { if (m == 1) return 0; unsigned int um = (unsigned int)m; unsigned long long r = 1; unsigned long long y = (unsigned long long)safe_mod(x, m); while (n) { if (n & 1) r = (r * y) % um; y = (y * y) % um; n >>= 1; } return (long long)r; } constexpr bool is_prime_constexpr(int n) { if (n <= 1) return false; if (n == 2 || n == 7 || n == 61) return true; if ((n & 1) == 0) return false; long long d = n - 1; while ((d & 1) == 0) d >>= 1; constexpr long long bases[3] = {2, 7, 61}; for (long long a : bases) { long long t = d; long long y = pow_mod_constexpr(a, t, n); while (t != n - 1 && y != 1 && y != n - 1) { y = (y * y) % n; t <<= 1; } if (y != n - 1 && (t & 1) == 0) return false; } return true; } template constexpr bool is_prime = is_prime_constexpr(n); constexpr std::pair inv_gcd(long long a, long long b) { a = safe_mod(a, b); if (a == 0) return {b, 0}; long long s = b, t = a; long long m0 = 0, m1 = 1; while (t) { long long u = s / t; s -= t * u; m0 -= m1 * u; std::swap(s, t); std::swap(m0, m1); } if (m0 < 0) m0 += b / s; return {s, m0}; } struct barrett { unsigned int m_; unsigned long long im_; explicit barrett(unsigned int m) : m_(m), im_((unsigned long long)(-1) / m + 1) {} unsigned int umod() const { return m_; } unsigned int mul(unsigned int a, unsigned int b) const { unsigned long long z = (unsigned long long)a * b; #ifdef _MSC_VER unsigned long long x; _umul128(z, im_, &x); #else unsigned long long x = (unsigned long long)(((__uint128_t)z * im_) >> 64); #endif unsigned long long y = x * m_; return (unsigned int)(z - y + (z < y ? m_ : 0)); } }; } // namespace internal template * = nullptr> struct static_modint : internal::static_modint_base { using Modint = static_modint; static constexpr int mod() { return m; } static Modint raw(int v) { Modint x; x.v_ = (unsigned int)v; return x; } static_modint() : v_(0) {} template * = nullptr> static_modint(T v) { long long x = (long long)(v % (long long)umod()); if (x < 0) x += umod(); v_ = (unsigned int)x; } template * = nullptr> static_modint(T v) { v_ = (unsigned int)(v % umod()); } int val() const { return (int)v_; } Modint &operator++() { ++v_; if (v_ == umod()) v_ = 0; return *this; } Modint &operator--() { if (v_ == 0) v_ = umod(); --v_; return *this; } Modint operator++(int) { Modint r = *this; ++*this; return r; } Modint operator--(int) { Modint r = *this; --*this; return r; } Modint &operator+=(const Modint &rhs) { v_ += rhs.v_; if (v_ >= umod()) v_ -= umod(); return *this; } Modint &operator-=(const Modint &rhs) { v_ -= rhs.v_; if (v_ >= umod()) v_ += umod(); return *this; } Modint &operator*=(const Modint &rhs) { unsigned long long z = (unsigned long long)v_ * rhs.v_; v_ = (unsigned int)(z % umod()); return *this; } Modint &operator/=(const Modint &rhs) { return *this *= rhs.inv(); } Modint operator+() const { return *this; } Modint operator-() const { return Modint() - *this; } Modint pow(long long n) const { assert(0 <= n); Modint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } Modint inv() const { if (prime_) { assert(v_ != 0); return pow((long long)umod() - 2); } auto eg = internal::inv_gcd((long long)v_, m); assert(eg.first == 1); return Modint((int)eg.second); } friend Modint operator+(Modint lhs, const Modint &rhs) { return lhs += rhs; } friend Modint operator-(Modint lhs, const Modint &rhs) { return lhs -= rhs; } friend Modint operator*(Modint lhs, const Modint &rhs) { return lhs *= rhs; } friend Modint operator/(Modint lhs, const Modint &rhs) { return lhs /= rhs; } friend bool operator==(const Modint &lhs, const Modint &rhs) { return lhs.v_ == rhs.v_; } friend bool operator!=(const Modint &lhs, const Modint &rhs) { return lhs.v_ != rhs.v_; } private: unsigned int v_; static constexpr unsigned int umod() { return (unsigned int)m; } static constexpr bool prime_ = internal::is_prime; }; template struct dynamic_modint : internal::modint_base { using Modint = dynamic_modint; static int mod() { return (int)bt_.umod(); } static void set_mod(int m) { assert(1 <= m); bt_ = internal::barrett((unsigned int)m); } static Modint raw(int v) { Modint x; x.v_ = (unsigned int)v; return x; } dynamic_modint() : v_(0) {} template * = nullptr> dynamic_modint(T v) { long long x = (long long)(v % (long long)mod()); if (x < 0) x += mod(); v_ = (unsigned int)x; } template * = nullptr> dynamic_modint(T v) { v_ = (unsigned int)(v % (unsigned int)mod()); } int val() const { return (int)v_; } Modint &operator++() { ++v_; if (v_ == umod()) v_ = 0; return *this; } Modint &operator--() { if (v_ == 0) v_ = umod(); --v_; return *this; } Modint operator++(int) { Modint r = *this; ++*this; return r; } Modint operator--(int) { Modint r = *this; --*this; return r; } Modint &operator+=(const Modint &rhs) { v_ += rhs.v_; if (v_ >= umod()) v_ -= umod(); return *this; } Modint &operator-=(const Modint &rhs) { v_ += umod() - rhs.v_; if (v_ >= umod()) v_ -= umod(); return *this; } Modint &operator*=(const Modint &rhs) { v_ = bt_.mul(v_, rhs.v_); return *this; } Modint &operator/=(const Modint &rhs) { return *this *= rhs.inv(); } Modint operator+() const { return *this; } Modint operator-() const { return Modint() - *this; } Modint pow(long long n) const { assert(0 <= n); Modint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } Modint inv() const { auto eg = internal::inv_gcd((long long)v_, mod()); assert(eg.first == 1); return Modint((int)eg.second); } friend Modint operator+(Modint lhs, const Modint &rhs) { return lhs += rhs; } friend Modint operator-(Modint lhs, const Modint &rhs) { return lhs -= rhs; } friend Modint operator*(Modint lhs, const Modint &rhs) { return lhs *= rhs; } friend Modint operator/(Modint lhs, const Modint &rhs) { return lhs /= rhs; } friend bool operator==(const Modint &lhs, const Modint &rhs) { return lhs.v_ == rhs.v_; } friend bool operator!=(const Modint &lhs, const Modint &rhs) { return lhs.v_ != rhs.v_; } private: unsigned int v_; static internal::barrett bt_; static unsigned int umod() { return bt_.umod(); } }; template internal::barrett dynamic_modint::bt_(998244353); using Modint9 = static_modint<998244353>; using Modint1 = static_modint<1000000007>; using Modint = dynamic_modint<-1>; namespace internal { template using is_static_modint = std::is_base_of; template using is_static_modint_t = std::enable_if_t::value>; template struct is_dynamic_modint : std::false_type { }; template struct is_dynamic_modint> : std::true_type { }; template using is_dynamic_modint_t = std::enable_if_t::value>; } // namespace internal } // namespace modint_lib template * = nullptr> using StaticModint = modint_lib::static_modint; template using DynamicModint = modint_lib::dynamic_modint; using Modint9 = modint_lib::Modint9; using Modint1 = modint_lib::Modint1; using Modint = modint_lib::Modint; #endif // MODINT_LIBRARY_MODINT_HPP // ===== END MODINT COPY BLOCK ===== int main() { // ここにコードを書く Modint::set_mod(10007); LL(k, s, n); vector F; rep0(i, k + 1) { if (i == 0 || i == 1) { F.push_back(1); } else { F.push_back((F[i - 1] + F[i - 2]) % 10007); } } vector A; rep0(i, n) { if (i == 0) { A.push_back(s); } else { Modint now = 0; ll no = 0; rrep(j, i - 1, max(i - 1 - k - 1, (ll)-1)) { Modint b = 0; b += A[j]; Modint inv = F[no]; b *= inv.inv(); now += b; // print(A[j], F[no]); no++; } // print(now.val()); // print("--------"); A.push_back(now.val() % 10007); } // print(A); } // print(F); print(A.back() % 10007); }