// #pragma GCC optimize("unroll-loops", "omit-frame-pointer", "inline") // #pragma GCC option("arch=native", "tune=native", "no-zero-upper") // #pragma GCC // target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native") // #pragma GCC optimize("Ofast") // #pragma GCC optimize("tree-vectorize","openmp","predictive-commoning") // #pragma GCC option("D_GLIBCXX_PARALLEL","openmp") // #pragma GCC optimize("O3") // #pragma GCC target("avx2") #include using namespace std; typedef long long ll; typedef pair P; #define eps 1e-9 #define INF 2000000000 // 2e9 #define LLINF 2000000000000000000ll // 2e18 (llmax:9e18) #define all(x) (x).begin(), (x).end() #define sq(x) ((x) * (x)) #ifndef LOCAL #define dmp(...) ; #else #define dmp(...) \ cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl #endif // ---------------- Utility ------------------ template bool chmin(T &a, const T &b) { if (a <= b) return false; a = b; return true; } template bool chmax(T &a, const T &b) { if (a >= b) return false; a = b; return true; } template using MaxHeap = priority_queue; template using MinHeap = priority_queue, greater>; template vector vect(int len, T elem) { return vector(len, elem); } // ----------------- Input ------------------- template istream &operator>>(istream &is, pair &p) { is >> p.first >> p.second; return is; } template istream &operator>>(istream &is, vector &vec) { for (int i = 0; i < vec.size(); i++) is >> vec[i]; return is; } // ----------------- Output ------------------ template ostream &operator<<(ostream &os, const pair &p) { os << p.first << ',' << p.second; return os; } template ostream &operator<<(ostream &os, const vector &v) { for (const T &e : v) os << e << " "; return os; } template ostream &operator<<(ostream &os, const deque &d) { for (const T &e : d) os << e << " "; return os; } template ostream &operator<<(ostream &os, const set &s) { os << "{ "; for (const T &e : s) os << e << " "; os << "}"; return os; } template ostream &operator<<(ostream &os, const multiset &s) { os << "{ "; for (const T &e : s) os << e << " "; os << "}"; return os; } template ostream &operator<<(ostream &os, const map &m) { os << "{ "; for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) "; os << "}"; return os; } void dump_str_rec(ostringstream &) {} template void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) { oss << ", " << head; dump_str_rec(oss, forward(tail)...); } template string dump_str(T &&arg, U &&... args) { ostringstream oss; oss << arg; dump_str_rec(oss, forward(args)...); return oss.str(); } // --------------- Fast I/O ------------------ void fastio() { cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(20); } // ------------ End of template -------------- #define endl "\n" struct AhoCorasick { const static int alphabet_size = 10; const int root = 0; const char base = '0'; AhoCorasick() : T(1) {} AhoCorasick(const vector &ss) : T(1) { for (const string &s : ss) add_string(s); build(); } struct Node { vector child; // children of this node in Trie bool leaf; int par; // parent char par_c; // character on the edge from parent to this node int suf_link; // suffix link vector go; // transition of the automaton int match_count; // the number of matches of this state Node(int par = -1, char par_c = '$') : leaf(false), par(par), par_c(par_c), suf_link(-1) { child.assign(alphabet_size, -1); go.assign(alphabet_size, -1); } }; vector T; void add_string(const string &s) { int v = root; for (char ch : s) { int c = ch - base; if (T[v].child[c] == -1) { T[v].child[c] = T.size(); T.emplace_back(v, ch); } v = T[v].child[c]; } T[v].leaf = true; } int suf_link(int v) { if (T[v].suf_link == -1) { if (v == root || T[v].par == root) { T[v].suf_link = root; } else { int par_suf_link = suf_link(T[v].par); T[v].suf_link = go(par_suf_link, T[v].par_c); } } return T[v].suf_link; } int go(int v, char ch) { int c = ch - base; if (T[v].go[c] == -1) { if (T[v].child[c] != -1) T[v].go[c] = T[v].child[c]; else T[v].go[c] = (v == root) ? root : go(suf_link(v), ch); } return T[v].go[c]; } int match_count(int v) { if (v == root) T[v].match_count = 0; else { T[v].match_count = match_count(suf_link(v)) + (T[v].leaf ? 1 : 0); } return T[v].match_count; } void build() { for (int v = 0; v < T.size(); v++) { suf_link(v); match_count(v); for (int i = 0; i < alphabet_size; i++) go(v, base + i); } } Node &operator[](int v) { return T[v]; } int size() const { return T.size(); } }; template // if inv is needed, this shold be prime. struct ModInt { ll val; ModInt() : val(0ll) {} ModInt(const ll &v) : val(((v % MOD) + MOD) % MOD) {} bool operator==(const ModInt &x) const { return val == x.val; } bool operator!=(const ModInt &x) const { return !(*this == x); } bool operator<(const ModInt &x) const { return val < x.val; } bool operator>(const ModInt &x) const { return val > x.val; } bool operator>=(const ModInt &x) const { return !(*this < x); } bool operator<=(const ModInt &x) const { return !(*this > x); } ModInt operator-() const { return ModInt(MOD - val); } ModInt inv() const { return this->pow(MOD - 2); } ModInt &operator+=(const ModInt &x) { if ((val += x.val) >= MOD) val -= MOD; return *this; } ModInt &operator-=(const ModInt &x) { if ((val += MOD - x.val) >= MOD) val -= MOD; return *this; } ModInt &operator*=(const ModInt &x) { (val *= x.val) %= MOD; return *this; } ModInt &operator/=(const ModInt &x) { return *this *= x.inv(); }; ModInt operator+(const ModInt &x) const { return ModInt(*this) += x; } ModInt operator-(const ModInt &x) const { return ModInt(*this) -= x; } ModInt operator*(const ModInt &x) const { return ModInt(*this) *= x; } ModInt operator/(const ModInt &x) const { return ModInt(*this) /= x; } friend istream &operator>>(istream &i, ModInt &x) { ll v; i >> v; x = v; return i; } friend ostream &operator<<(ostream &o, const ModInt &x) { o << x.val; return o; } ModInt pow(ll x) const { auto res = ModInt(1ll); auto b = *this; while (x) { if (x & 1) res *= b; x >>= 1; b *= b; } return res; } }; template ModInt pow(ModInt a, ll x) { ModInt res = ModInt(1ll); while (x) { if (x & 1) res *= a; x >>= 1; a *= a; } return res; } constexpr int MOD = 1e9 + 7; // constexpr int MOD = 998244353; using mint = ModInt; void solve() { int N; ll L, R; cin >> N >> L >> R; ll x = 1, y = 1; vector vs; while (LLINF - x >= y) { if (L <= y && y <= R) vs.push_back(to_string(y)); ll z = x + y; x = y; y = z; } AhoCorasick ac(vs); auto dp = vect(N + 1, vect(ac.size(), mint(0))); dp[0][0] = mint(1); for (int i = 0; i < N; i++) { for (int j = 0; j < ac.size(); j++) { for (int k = 0; k < 10; k++) { int next_state = ac.go(j, '0' + k); if (ac[next_state].match_count > 0) continue; dp[i + 1][next_state] += dp[i][j]; } } } mint ans(0); for (int j = 0; j < ac.size(); j++) ans += dp[N][j]; ans -= mint(1); cout << ans << endl; return; } int main() { fastio(); solve(); // int t; cin >> t; while(t--)solve(); // int t; cin >> t; // for(int i=1;i<=t;i++){ // cout << "Case #" << i << ": "; // solve(); // } return 0; }