#include <bits/stdc++.h>
const int mod = 1000000007;
const int gmod = 3;
const int inf = 1039074182;
const double eps = 1e-9;
const long long llinf = 2LL * inf * inf;
template <typename T1, typename T2>
inline void chmin(T1 &x, T2 b) {
  if (b < x) x = b;
}
template <typename T1, typename T2>
inline void chmax(T1 &x, T2 b) {
  if (b > x) x = b;
}
inline void chadd(int &x, int b) {
  x += b - mod;
  x += (x >> 31 & mod);
}
template <typename T1, typename T2>
inline void chadd(T1 &x, T2 b) {
  x += b;
  if (x >= mod) x -= mod;
}
template <typename T1, typename T2>
inline void chmul(T1 &x, T2 b) {
  x = 1LL * x * b % mod;
}
template <typename T1, typename T2>
inline void chmod(T1 &x, T2 b) {
  x %= b, x += b;
  if (x >= b) x -= b;
}
template <typename T>
inline T mabs(T x) {
  return (x < 0 ? -x : x);
}
using namespace std;
using namespace std;
template <typename T>
ostream &operator<<(ostream &cout, vector<T> vec) {
  cout << "{";
  for (int i = 0; i < (int)vec.size(); i++) {
    cout << vec[i];
    if (i != (int)vec.size() - 1) cout << ',';
  }
  cout << "}";
  return cout;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &cout, pair<T1, T2> p) {
  cout << "(" << p.first << ',' << p.second << ")";
  return cout;
}
template <typename T, typename T2>
ostream &operator<<(ostream &cout, set<T, T2> s) {
  vector<T> t;
  for (auto x : s) t.push_back(x);
  cout << t;
  return cout;
}
template <typename T, typename T2>
ostream &operator<<(ostream &cout, multiset<T, T2> s) {
  vector<T> t;
  for (auto x : s) t.push_back(x);
  cout << t;
  return cout;
}
template <typename T>
ostream &operator<<(ostream &cout, queue<T> q) {
  vector<T> t;
  while (q.size()) {
    t.push_back(q.front());
    q.pop();
  }
  cout << t;
  return cout;
}
template <typename T1, typename T2, typename T3>
ostream &operator<<(ostream &cout, map<T1, T2, T3> m) {
  for (auto &x : m) {
    cout << "Key: " << x.first << ' ' << "Value: " << x.second << endl;
  }
  return cout;
}
template <typename T1, typename T2>
void operator+=(pair<T1, T2> &x, const pair<T1, T2> y) {
  x.first += y.first;
  x.second += y.second;
}
template <typename T1, typename T2>
pair<T1, T2> operator+(const pair<T1, T2> &x, const pair<T1, T2> &y) {
  return make_pair(x.first + y.first, x.second + y.second);
}
template <typename T1, typename T2>
pair<T1, T2> operator-(const pair<T1, T2> &x, const pair<T1, T2> &y) {
  return make_pair(x.first - y.first, x.second - y.second);
}
template <typename T1, typename T2>
pair<T1, T2> operator-(pair<T1, T2> x) {
  return make_pair(-x.first, -x.second);
}
template <typename T>
vector<vector<T>> operator~(vector<vector<T>> vec) {
  vector<vector<T>> v;
  int n = vec.size(), m = vec[0].size();
  v.resize(m);
  for (int i = 0; i < m; i++) {
    v[i].resize(n);
  }
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      v[i][j] = vec[j][i];
    }
  }
  return v;
}
void print0x(int x) {
  std::vector<int> vec;
  while (x) {
    vec.push_back(x & 1);
    x >>= 1;
  }
  std::reverse(vec.begin(), vec.end());
  for (int i = 0; i < (int)vec.size(); i++) {
    std::cout << vec[i];
  }
  std::cout << ' ';
}
template <typename T>
void print0x(T x, int len) {
  std::vector<int> vec;
  while (x) {
    vec.push_back(x & 1);
    x >>= 1;
  }
  reverse(vec.begin(), vec.end());
  for (int i = (int)vec.size(); i < len; i++) {
    putchar('0');
  }
  for (size_t i = 0; i < vec.size(); i++) {
    std::cout << vec[i];
  }
  std::cout << ' ';
}
vector<string> vec_splitter(string s) {
  s += ',';
  vector<string> res;
  while (!s.empty()) {
    res.push_back(s.substr(0, s.find(',')));
    s = s.substr(s.find(',') + 1);
  }
  return res;
}
void debug_out(vector<string> __attribute__((unused)) args,
               __attribute__((unused)) int idx,
               __attribute__((unused)) int LINE_NUM) {
  cerr << endl;
}
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, int LINE_NUM, Head H, Tail... T) {
  if (idx > 0)
    cerr << ", ";
  else
    cerr << "Line(" << LINE_NUM << ") ";
  stringstream ss;
  ss << H;
  cerr << args[idx] << " = " << ss.str();
  debug_out(args, idx + 1, LINE_NUM, T...);
}
template <int mod>
struct ModInt {
  int x;
  ModInt() { x = 0; }
  ModInt(int _x) {
    x = _x % mod;
    if (x < 0) x += mod;
  }
  ModInt(long long _x) {
    x = _x % mod;
    if (x < 0) x += mod;
  }
  ModInt<mod> &operator++() {
    ++x;
    if (x == mod) x = 0;
    return *this;
  }
  ModInt<mod> operator++(int) {
    int t = x;
    x++;
    if (x == mod) x = 0;
    return t;
  }
  ModInt<mod> &operator--() {
    --x;
    if (x == -1) x += mod;
    return *this;
  }
  ModInt<mod> operator--(int) {
    int t = x;
    x--;
    if (x == -1) x += mod;
    return t;
  }
  ModInt<mod> operator-() const { return ModInt<mod>((x == 0 ? 0 : mod - x)); }
};
template <int mod>
inline int mabs(const ModInt<mod> &a) {
  return a.x;
}
template <int mod>
bool operator==(const ModInt<mod> &a, const ModInt<mod> &b) {
  return a.x == b.x;
}
template <int mod>
bool operator==(ModInt<mod> a, int x) {
  return (a.x == x);
}
template <int mod>
bool operator!=(const ModInt<mod> &a, const ModInt<mod> &b) {
  return (a.x != b.x);
}
template <int mod>
bool operator!=(ModInt<mod> a, int x) {
  return (a.x != x);
}
template <int mod>
inline ModInt<mod> operator+(ModInt<mod> a, int b) {
  a.x += b;
  if (a.x >= mod) a.x -= mod;
  return a;
}
template <int mod>
inline ModInt<mod> operator+(ModInt<mod> a, ModInt<mod> b) {
  int tmp = a.x + b.x;
  if (tmp >= mod) tmp -= mod;
  return tmp;
}
template <int mod>
inline ModInt<mod> operator-(ModInt<mod> a, ModInt<mod> b) {
  int tmp = a.x - b.x;
  if (tmp < 0) tmp += mod;
  return tmp;
}
template <int mod>
inline ModInt<mod> operator-(ModInt<mod> a, int b) {
  return a - (ModInt<mod>)b;
}
template <int mod>
inline void operator-=(ModInt<mod> &a, ModInt<mod> b) {
  a.x -= b.x;
  a.x += (a.x >> 31 & mod);
}
template <int mod, typename T>
inline void operator-=(ModInt<mod> &a, const T &b) {
  a.x -= b;
  a.x += (a.x >> 31 & mod);
}
template <int mod>
inline ModInt<mod> operator*(const ModInt<mod> &a, const ModInt<mod> &b) {
  return 1LL * a.x * b.x % mod;
}
template <int mod>
inline ModInt<mod> operator*(const ModInt<mod> &a, const int &b) {
  return 1LL * a.x * b % mod;
}
template <int mod>
inline void operator*=(ModInt<mod> &a, const ModInt<mod> &b) {
  a.x = 1LL * a.x * b.x % mod;
}
template <int mod, typename T>
inline void operator*=(ModInt<mod> &a, const T &b) {
  a = a * b;
}
template <int mod>
inline void operator+=(ModInt<mod> &a, const ModInt<mod> &b) {
  a.x += b.x;
  if (a.x >= mod) a.x -= mod;
}
template <int mod, typename T>
void operator+=(ModInt<mod> &a, const T &b) {
  a.x += b;
  if (a.x >= mod) a.x -= mod;
}
template <int mod>
inline ModInt<mod> mod_inv(ModInt<mod> x) {
  int m = mod - 2;
  ModInt<mod> basic = x;
  x = 1;
  while (m) {
    if (m & 1) x *= basic;
    m >>= 1;
    basic *= basic;
  }
  return x;
}
template <int mod>
ModInt<mod> operator/(ModInt<mod> a, ModInt<mod> b) {
  return a * mod_inv(b);
}
template <int mod>
ModInt<mod> operator/(ModInt<mod> a, int b) {
  return a * mod_inv((ModInt<mod>)b);
}
template <int mod>
void operator/=(ModInt<mod> &a, int b) {
  a *= mod_inv(ModInt<mod>(b));
}
template <int mod>
void operator/=(ModInt<mod> &a, ModInt<mod> b) {
  a = a / b;
}
template <int mod>
inline ModInt<mod> operator^(ModInt<mod> basic, int x) {
  ModInt<mod> res = 1;
  while (x) {
    if (x & 1) res *= basic;
    basic *= basic;
    x >>= 1;
  }
  return res;
}
template <int mod>
istream &operator>>(istream &cin, ModInt<mod> &x) {
  cin >> x.x;
  x.x %= mod;
  if (x.x < 0) x.x += mod;
  return cin;
}
template <int mod>
ostream &operator<<(ostream &cout, ModInt<mod> x) {
  cout << x.x;
  return cout;
}
template <int mod, int g, int LogN>
struct NTT {
  using Int = ModInt<mod>;
  static const int MaxN = (1 << LogN);
  int w[MaxN + 5];
  int fastpow(int basic, int x) {
    int res = 1;
    while (x) {
      if (x & 1) res = 1LL * res * basic % mod;
      basic = 1LL * basic * basic % mod;
      x >>= 1;
    }
    return res;
  }
  int inv[MaxN + 5];
  int buf[MaxN + 5];
  int ww[MaxN + 5];
  inline void ntt(vector<int> &v, int rev, int lg) {
    int n = (1 << lg);
    memset(buf, 0, sizeof(int) * n);
    v.resize(n, 0);
    for (int i = 0; i < n; i++) {
      inv[i] = (inv[i >> 1] >> 1) | ((i & 1) << (lg - 1));
    }
    for (int i = 0; i < n; i++) {
      buf[i] = v[inv[i]];
    }
    int lvl = LogN;
    int *ba, *bb, *wa, *wb;
    int tmp;
    for (int b = 1; b < n; b *= 2) {
      lvl--;
      for (int i = 0; i < b * 2; i++)
        ww[i] = (rev ? w[MaxN - (i << lvl)] : w[i << lvl]);
      for (int i = 0; i < n; i += b * 2) {
        ba = buf + i;
        bb = buf + i + b;
        wa = ww;
        wb = ww + b;
        for (int j = 0; j < b; j++) {
          tmp = 1LL * *wa * *bb % mod;
          *bb = *ba - tmp;
          *ba += tmp;
          *ba -= mod;
          *ba += ((*ba) >> 31 & mod);
          *bb += ((*bb) >> 31 & mod);
          ba++;
          bb++;
          wa++;
          wb++;
        }
      }
    }
    int t = fastpow(n, mod - 2);
    if (rev) {
      for (int i = 0; i < (1 << lg); i++) {
        buf[i] = 1LL * buf[i] * t % mod;
      }
    }
    for (int i = 0; i < (1 << lg); i++) v[i] = buf[i];
  }
  void multiply(vector<int> a, vector<int> b, vector<int> &c) {
    int n = (int)a.size() + b.size() - 1;
    if (min(a.size(), b.size()) <= 60) {
      c.clear();
      c.resize(max(0, n), 0);
      for (int i = 0; i < (int)a.size(); i++) {
        for (int j = 0; j < (int)b.size(); j++) {
          c[i + j] = (1LL * a[i] * b[j] + c[i + j]) % mod;
        }
      }
      while (c.size() && c.back() == 0) c.pop_back();
    }
    int nn = 1, lg = 0;
    while (nn < n) {
      nn <<= 1;
      lg++;
    }
    c.resize(nn);
    a.resize(nn, 0);
    b.resize(nn, 0);
    ntt(a, 0, lg);
    ntt(b, 0, lg);
    for (int i = 0; i < nn; i++) {
      c[i] = 1LL * a[i] * b[i] % mod;
    }
    ntt(c, 1, lg);
    while (c.size() && c.back() == 0) c.pop_back();
  }
  void sqr(vector<int> &a) {
    int n = (int)a.size() + a.size() - 1;
    int nn = 1, lg = 0;
    while (nn < n) {
      nn <<= 1;
      lg++;
    }
    a.resize(nn, 0);
    ntt(a, 0, lg);
    for (int i = 0; i < nn; i++) {
      a[i] = 1LL * a[i] * a[i] % mod;
    }
    ntt(a, 1, lg);
    while (a.size() && a.back() == 0) a.pop_back();
  }
  vector<Int> multiply(const vector<Int> &a, const vector<Int> &b) {
    vector<int> ta(a.size()), tb(b.size());
    for (int i = 0; i < (int)a.size(); i++) ta[i] = a[i].x;
    for (int i = 0; i < (int)b.size(); i++) tb[i] = b[i].x;
    vector<int> tc;
    multiply(ta, tb, tc);
    vector<Int> c(tc.size());
    for (int i = 0; i < (int)c.size(); i++) c[i].x = tc[i];
    return c;
  }
  NTT() {
    w[0] = 1;
    int ur = fastpow(g, (mod - 1) >> LogN);
    for (int i = 1; i <= MaxN; i++) {
      w[i] = 1LL * w[i - 1] * ur % mod;
    }
  }
};
using namespace std;
int n, k;
int fac[30005];
int ifac[30005];
inline int fastpow(long long basic, int x) {
  long long res = 1;
  while (x) {
    if (x & 1) (res *= basic) %= mod;
    (basic *= basic) %= mod;
    x >>= 1;
  }
  return res;
}
vector<int> Ex;
vector<int> Ex1;
inline int fastpow(long long basic, int x, int mod) {
  long long res = 1;
  while (x) {
    if (x & 1) (res *= basic) %= mod;
    (basic *= basic) %= mod;
    x >>= 1;
  }
  return res;
}
template <int mod>
struct MTT {
  NTT<998244353, 3, 17> ntt1;
  NTT<469762049, 3, 17> ntt2;
  NTT<1004535809, 3, 17> ntt3;
  static const int p1 = 998244353;
  static const int p2 = 469762049;
  static const int p3 = 1004535809;
  vector<int> c1, c2, c3;
  inline void multiply(vector<int> a, vector<int> b, vector<int> &c) {
    ntt1.multiply(a, b, c1);
    ntt2.multiply(a, b, c2);
    ntt3.multiply(a, b, c3);
    c.clear();
    int n = max({c1.size(), c2.size(), c3.size()});
    c1.resize(n, 0);
    c2.resize(n, 0);
    c3.resize(n, 0);
    c.resize(n);
    for (int i = 0; i < n; i++) {
      int x = c1[i];
      int y = c2[i];
      int z = c3[i];
      long long t =
          (1LL * (x - y + p1) * fastpow(p2, p1 - 2, p1) % p1 * p2 + y);
      c[i] = (1LL * ((z - t) % p3 + p3) % p3 * fastpow(p2, p3 - 2, p3) % p3 *
                  fastpow(p1, p3 - 2, p3) % p3 * p1 % mod * p2 % mod +
              t % mod) %
             mod;
    }
  }
};
MTT<mod> mtt;
inline void multiply(vector<int> a, vector<int> b, vector<int> &c) {
  mtt.multiply(a, b, c);
}
inline vector<int> replacex(vector<int> x, int len) {
  int v = fastpow(2, len);
  for (int i = 0; i < x.size(); i++) {
    x[i] = 1LL * x[i] * fastpow(v, i) % mod;
  }
  return x;
}
vector<int> fastpow(int n) {
  vector<int> res;
  res.push_back(1);
  int len = 0;
  for (int i = 14; i >= 0; i--) {
    if ((1 << i) & n) multiply(replacex(res, 1), Ex1, res), len++;
    if (i) multiply(replacex(res, len), res, res), len <<= 1;
    if (res.size() > k) res.resize(k + 1);
  }
  return res;
}
int main() {
  fac[0] = 1;
  for (int i = 1; i <= 30000; i++) fac[i] = 1LL * fac[i - 1] * i % mod;
  for (int i = 0; i <= 30000; i++) ifac[i] = fastpow(fac[i], mod - 2);
  long long _n;
  cin >> _n >> k;
  if (_n > k) {
    cout << 0 << endl;
    exit(0);
  };
  n = _n;
  for (int i = 0; i <= k; i++) Ex.push_back(ifac[i]);
  Ex1 = Ex;
  Ex1[0] = 0;
  vector<int> v = fastpow(n);
  multiply(v, Ex, v);
  cout << 1LL * v[k] * fac[k] % mod << endl;
  return 0;
}
