Problem p01450 (C++) — buggy submission, verdict: Memory Limit Exceeded

////////////////////
///   template   ///
////////////////////
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

//// MACRO ////
#define countof(a) (sizeof(a) / sizeof(a[0]))

#define REP(i, n) for (int i = 0; i < (n); i++)
#define RREP(i, n) for (int i = (n)-1; i >= 0; i--)
#define FOR(i, s, n) for (int i = (s); i < (n); i++)
#define pos(c, i) c.being() + (i)
#define allof(c) c.begin(), c.end()
#define aallof(a) a, countof(a)
#define partof(c, i, n) c.begin() + (i), c.begin() + (i) + (n)
#define apartof(a, i, n) a + (i), a + (i) + (n)
#define long long long

#define EPS 1e-10
#define INF 1000000000

#define PREDIACTE(t, a) [](const t &a) -> bool
#define COMPARISON_T(t) bool (*)(const t &, const t &)
#define COMPARISON(t, a, b) [](const t &a, const t &b) -> bool

//// algorithm ////

// compare
template <class InIt1, class InIt2>
int partial_compare(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2) {
  return lexicographical_compare(first1, last1, first2, last2)   ? -1
         : lexicographical_compare(first2, last2, first1, last1) ? 1
                                                                 : 0;
}

// index_of
template <class InIt, class T>
inline int index_of(InIt first1, InIt last1, const T &val) {
  InIt f = find(first1, last1, val);
  return f != last1 ? distance(f, first1) : -1;
}

// C# BinarySearch風のindex_of
template <class InIt, class T>
inline int bindex_of(InIt first1, InIt last1, const T &val) {
  auto it = lower_bound(first1, last1, val);
  if (it == last1) {
    return ~distance(it, first1);
  } else if (*it == val) {
    return distance(it, first1);
  } else
    return ~distance(it, first1);
}

// vector iota iterator
vector<int> iotav(int begin, int end) {
  vector<int> r(end - begin);
  iota(allof(r), begin);
  return r;
}

struct iotait {
  int n;
  iotait(int n = 0) : n(n) {}
  iotait &operator++() {
    ++n;
    return *this;
  }
  int operator*() { return n; }
};

// 最大公約数
long gcd(long a, long b) { return b ? gcd(b, a % b) : a; }

// 最小公倍数
long lcm(long a, long b) { return a / gcd(a, b) * b; }

// 拡張ユークリッド互除法
void exgcd(long a, long b, long &x, long &y) {
  if (b != 0) {
    exgcd(b, a % b, y, x);
    y -= a / b * x;
  } else {
    x = 1;
    y = 0;
  }
}

//// data structure ////

/// 2分セグメント木。RMQとかが解ける。
template <class T = int, class TParentFunc = const T &(*)(const T &, const T &)>
struct SegTree {
  int count;
  vector<T> tree;
  TParentFunc parent;

  SegTree(int size, TParentFunc parentBuilder = std::min, T initialFill = INF)
      : count((size | size - 1) + 1), tree(count * 2), parent(parentBuilder) {
    fill(partof(tree, count, count), initialFill);
    rebuild();
  }

  // []を使うと更新されないのでrebuildすること。数が少なければupdateの方がよい。
  T &operator[](int i) { return tree[i + count]; }
  void rebuild() {
    RREP(i, count) { tree[i] = parent(tree[i * 2], tree[i * 2 + 1]); }
  }

  void update(int index, T value) {
    tree[index + count] = value;
    for (int i = (index + count) / 2; i > 0; i /= 2)
      tree[i] = parent(tree[i * 2], tree[i * 2 + 1]);
  }

  T query(int s, int e, int i, int l, int r, T value) {
    if (r <= s || e <= l)
      return value;
    if (s <= l && r <= e)
      return parent(value, tree[i]);
    value = query(s, e, i * 2, l, (l + r) / 2, value);
    value = query(s, e, i * 2 + 1, (l + r) / 2, r, value);
    return value;
  }

  T query(int start, int count, T initialValue) {
    return query(start, start + count, 1, 0, count, initialValue);
  }
};

//// prime ////
vector<unsigned char> isPrime;
vector<int> primes;
void initPrimes(int n) {
  isPrime = vector<unsigned char>(n + 1, true);
  isPrime[0] = isPrime[1] = false;
  FOR(i, 2, n + 1) {
    if (!isPrime[i])
      continue;
    primes.push_back(i);
    for (int j = i * 2; j <= n; j += i)
      isPrime[j] = false;
  }
}

//// Probability ////

// パスカルの三角形(二項定理) 2種類の並べ替えにつかう。
vector<vector<double>> makePascalTriangle(int n, bool probability = false) {
  typedef vector<double> VD;
  vector<VD> t;
  if (!t.size()) {
    t.push_back(VD(1, 1));
  }
  FOR(i, t.size(), n + 1) {
    t.push_back(VD(i + 1));
    REP(j, i) {
      double x = t[i - 1][j] * (probability ? 0.5 : 1);
      t[i][j] += x;
      t[i][j + 1] += x;
    }
  }
  return t;
}

//// geo ////

/// 3次元
struct P3 {
  double x, y, z;
  P3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
  P3 operator+() const { return *this; }
  P3 operator+(const P3 &_) const { return P3(x + _.x, y + _.y, z + _.z); }
  P3 operator-() const { return P3(-x, -y, -z); }
  P3 operator-(const P3 &_) const { return *this + -_; }
  P3 operator*(double _) const { return P3(x * _, y * _, z * _); }
  P3 operator/(double _) const { return P3(x / _, y / _, z / _); }
  double dot(const P3 &_) const { return x * _.x + y * _.y + z * _.z; } // 内積
  P3 cross(const P3 &_) const {
    return P3(y * _.z - z * _.y, z * _.x - x * _.z, x * _.y - y * _.x);
  }                                                         // 外積
  double sqlength() const { return x * x + y * y + z * z; } // 二乗長さ
  double length() const { return sqrt(sqlength()); }        // 長さ
  P3 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream &operator>>(istream &in, P3 &p) {
  in >> p.x >> p.y >> p.z;
  return in;
}
inline double abs(P3 p) { return p.length(); }

struct Sphere {
  P3 c;
  double r;
  Sphere(double x, double y, double z, double r) : c(x, y, z), r(r) {}
  Sphere(P3 c, double r) : c(c), r(r) {}
  bool IntersectWith(const Sphere &rhs) const {
    return abs(c - rhs.c) - (r + rhs.r) < EPS;
  } // 接してても真。
};
inline istream &operator>>(istream &in, Sphere &c) {
  in >> c.c >> c.r;
  return in;
}

/// 2次元
struct P2 {
  double x, y;
  P2(double x = 0, double y = 0) : x(x), y(y) {}
  P2(complex<double> c) : x(c.real()), y(c.imag()) {}
  P2 operator+() const { return *this; }
  P2 operator+(const P2 &_) const { return P2(x + _.x, y + _.y); }
  P2 operator-() const { return P2(-x, -y); }
  P2 operator-(const P2 &_) const { return *this + -_; }
  P2 operator*(double _) const { return P2(x * _, y * _); }
  P2 operator/(double _) const { return P2(x / _, y / _); }
  double dot(const P2 &_) const { return x * _.x + y * _.y; }   // 内積
  double cross(const P2 &_) const { return x * _.y - y * _.x; } // 外積
  double sqlength() const { return x * x + y * y; }             // 二乗長さ
  double length() const { return sqrt(sqlength()); }            // 長さ
  P2 orthogonal() const { return P2(y, -x); }
  P2 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream &operator>>(istream &in, P2 &p) {
  in >> p.x >> p.y;
  return in;
}
inline double abs(P2 p2) { return p2.length(); }
inline P2 orthogonal(P2 p) { return p.orthogonal(); }
inline complex<double> orthogonal(complex<double> c) {
  return c * complex<double>(0, 1);
}

// a,b から ちょうど d だけ離れた点。aとbを円周に持つ円の半径。
inline pair<P2, P2> get_same_distance_points(P2 a, P2 b, double d) {
  assert(abs(a - b) <= 2 * d + EPS);
  auto v = (a + b) / 2.0 - a; // a から aとbの中点
  auto vl = abs(v);
  auto wl = sqrt(d * d - vl * vl);    // 直行Vの大きさ
  auto w = orthogonal(v) * (wl / vl); // 直行V
  return make_pair(a + v + w, a + v - w);
}

struct Circle {
  P2 c;
  double r;
  Circle(double x, double y, double r) : c(x, y), r(r) {}
  Circle(P2 c, double r) : c(c), r(r) {}
  bool IntersectWith(const Circle &rhs) const {
    return abs(c - rhs.c) - (r + rhs.r) < EPS;
  } // 接してても真。
  bool Contains(const P2 &p) const {
    return abs(p - c) - r < EPS;
  } // 接してても真。
};
inline istream &operator>>(istream &in, Circle &c) {
  in >> c.c >> c.r;
  return in;
}

//// bit ////
#ifdef _MSC_VER
#pragma push_macro("long")
#undef long
inline unsigned __builtin_ctz(unsigned x) {
  unsigned long r;
  _BitScanForward(&r, x);
  return r;
}
#pragma pop_macro("long")
#endif

inline int next_bit_permutation(int x) {
  int t = x | (x - 1);
  return (t + 1) | (unsigned)((~t & -~t) - 1) >> (__builtin_ctz(x) + 1);
}

// x の p1からlen bitと p2 から len bit を入れ替える
template <class T> int bit_swap(T x, size_t p1, size_t p2, size_t len) {
  T mask = (1ul << len) - 1;
  T ope = (x >> p1 ^ x >> p2) & mask; // 入れ替える場所のxorを求める
  return x ^ (ope << p1 | ope << p2); // 入れ替える場所をxor。
}

//// graph ////
struct Path {
  int from;
  int to;
  double cost;
  double capacity;
  Path(int from = 0, int to = 0, double cost = 0, double capacity = -1)
      : from(from), to(to), cost(cost), capacity(capacity) {}
  bool operator<(const Path &rhs) const { return cost < rhs.cost; }
  bool operator>(const Path &rhs) const { return cost > rhs.cost; }
};

// prim //
pair<double, vector<int>> prim(const vector<vector<double>> &costTable) {
  int N = costTable.size();
  priority_queue<Path, vector<Path>, greater<Path>> q;
  q.push(Path(0, 0, 0));

  vector<int> parent(N, -1);
  double totalCost = 0;
  while (!q.empty()) {
    Path cur = q.top();
    q.pop();
    int i = cur.to;
    if (parent[i] != -1)
      continue;
    parent[i] = cur.from;
    totalCost += cur.cost;
    REP(j, N) if (parent[j] == -1) q.push(Path(i, j, costTable[i][j]));
  }
  return make_pair(totalCost, parent);
}

// dijkstra //
pair<vector<double>, vector<int>> dijkstra(const vector<vector<Path>> &routes,
                                           int start = 0, int goal = -1) {
  int N = routes.size();
  priority_queue<Path, vector<Path>, greater<Path>> q;
  q.push(Path(start, start, 0));

  vector<int> prev(N, -1);
  vector<double> cost(N, INF);
  while (!q.empty()) {
    Path cur = q.top();
    q.pop();
    int i = cur.to;
    if (prev[i] != -1)
      continue;
    prev[i] = cur.from;
    cost[i] = cur.cost;
    if (i == goal) {
      break;
    }
    REP(j, routes[i].size()) {
      Path next = Path(i, routes[i][j].to, cur.cost + routes[i][j].cost);
      if (prev[next.to] == -1)
        q.push(next);
    }
  }
  return make_pair(cost, prev);
}

//// dice ////

// さいころ
template <class T> struct Die {
  /* v as 天一地六東五西二南三北四
  |3|
  |1|0|4|5|
  |2|
  */
  T v[6];

  void rt(int x, int y, int z, int w) {
    swap(v[x], v[y]);
    swap(v[x], v[z]);
    swap(v[x], v[w]);
  }
  void rotateLeft() { rt(0, 4, 5, 1); }
  void rotateRight() { rt(1, 5, 4, 0); }
  void rotateDown() { rt(0, 3, 5, 2); }
  void rotateUp() { rt(2, 5, 3, 0); }
  void rotateCw() { rt(3, 1, 2, 4); }
  void rotateCcw() { rt(4, 2, 1, 3); }
  bool operator<(const Die &rhs) const {
    return lexicographical_compare(aallof(v), aallof(rhs.v));
  }
  bool operator==(const Die &rhs) const { return equal(aallof(v), rhs.v); }
  bool operator!=(const Die &rhs) const { return !equal(aallof(v), rhs.v); }
};

// 8面体
template <class T> struct Octahedra {
  /* v as
  /0\\/1\\/2\\/3\\
  \\4/\\5/\\6/\\7/
  */
  T v[8];

  void rt(int x, int y, int z, int w) {
    swap(v[x], v[y]);
    swap(v[x], v[z]);
    swap(v[x], v[w]);
  }
  void rotateLeft() {
    rt(0, 1, 2, 3);
    rt(4, 5, 6, 7);
  }
  void rotateRight() {
    rt(3, 2, 1, 0);
    rt(7, 6, 5, 4);
  }
  void rotateDown() {
    rt(0, 4, 7, 3);
    rt(1, 5, 6, 2);
  }
  void rotateUp() {
    rt(3, 7, 4, 0);
    rt(2, 6, 5, 2);
  }
  void rotateCw() {
    rt(0, 1, 5, 4);
    rt(3, 2, 6, 7);
  }
  void rotateCcw() {
    rt(4, 5, 1, 0);
    rt(7, 6, 1, 3);
  }
  bool operator<(const Octahedra &rhs) const {
    return lexicographical_compare(aallof(v), aallof(rhs.v));
  }
  bool operator==(const Octahedra &rhs) const {
    return equal(aallof(v), rhs.v);
  }
  bool operator!=(const Octahedra &rhs) const {
    return !equal(aallof(v), rhs.v);
  }
};

//// i/o ////
template <class T> class vevector : public vector<vector<T>> {
public:
  vevector(int n = 0, int m = 0) : vector<vector<T>>(n, vector<T>(m)){};
  vevector(int n, int m, const T &initial)
      : vector<vector<T>>(n, vector<T>(m, initial)){};
};

template <class T> T read() {
  T t;
  cin >> t;
  return t;
}
template <class T> vector<T> read(int n) {
  vector<T> v;
  REP(i, n) { v.push_back(read<T>()); }
  return v;
}
template <class T> vevector<T> read(int n, int m) {
  vevector<T> v;
  REP(i, n) v.push_back(read<T>(m));
  return v;
}
template <class T> vevector<T> readjag(int n) {
  vevector<T> v;
  REP(i, n) v.push_back(read<T>(read<int>()));
  return v;
}
struct _Reader {
  template <class T> _Reader operator,(T &rhs) {
    cin >> rhs;
    return *this;
  }
};
#define READ(t, ...)                                                           \\
  t __VA_ARGS__;                                                               \\
  _Reader(), __VA_ARGS__

template <class T> void write(const T &t) { cout << t << endl; }
template <class T, class T2> void write(const T &t, const T2 &t2) {
  cout << t << ' ' << t2 << endl;
}
template <class T> void write(const vector<T> &v) {
  ostringstream ss;
  for (auto x : v)
    ss << x << ' ';
  auto s = ss.str();
  cout << s.substr(0, s.length() - 1) << endl;
}

//// start up ////
void solve();
int main() {
  // freopen("A.in", "r", stdin);
  solve();
  return 0;
}

////////////////////
/// template end ///
////////////////////

#define MOD 1000000007

int dfs(const vector<int> &we, const vector<int> &wsum, vevector<int> &memo,
        int cur, int weight, int weLastSkiped, vector<int> &dbg) {
  if (cur == -1) {
    if (weight >= we[weLastSkiped]) {
      return 0;
    } // とらなくてはいけないアイテムをとってない。
    return 1;
  }

  // のこりのアイテムをすべてとっても、かばんに余裕ができてしまう。
  if (we[weLastSkiped] + wsum[cur] <= weight) {
    return 0;
  }

  // そうじゃないとき、
  if (memo[cur][weight] != -1) {
    return memo[cur][weight];
  }

  int pat = 0;
  // かばんにはいる
  if (weight >= we[cur]) {
    dbg.push_back(we[cur]);
    pat += dfs(we, wsum, memo, cur - 1, weight - we[cur], weLastSkiped, dbg);
    pat %= MOD;
    dbg.pop_back();
  }

  // これをかばんにいれない
  {
    pat += dfs(we, wsum, memo, cur - 1, weight, cur, dbg);
    pat %= MOD;
  }

  // write(vector<int>{cur, weight, pat});
  return memo[cur][weight] = pat;
}

void solve() {
  auto testcases = INF; // read<int>();
  REP(testcase, testcases) {
    READ(int, n, w);
    auto we = read<int>(n);
    we.push_back(INF);
    n++;
    sort(allof(we));

    auto wesum = vector<int>();
    partial_sum(allof(we), back_inserter(wesum));

    vevector<int> memo(n + 1, w + 1, -1);
    auto dbg = vector<int>();
    int ret = dfs(we, wesum, memo, n - 2, w, n - 1, dbg);
    write(ret);

    break;
  }
}

Error: MLE

Fixed submission:

////////////////////
///   template   ///
////////////////////
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

//// MACRO ////
#define countof(a) (sizeof(a) / sizeof(a[0]))

#define REP(i, n) for (int i = 0; i < (n); i++)
#define RREP(i, n) for (int i = (n)-1; i >= 0; i--)
#define FOR(i, s, n) for (int i = (s); i < (n); i++)
#define pos(c, i) c.being() + (i)
#define allof(c) c.begin(), c.end()
#define aallof(a) a, countof(a)
#define partof(c, i, n) c.begin() + (i), c.begin() + (i) + (n)
#define apartof(a, i, n) a + (i), a + (i) + (n)
#define long long long

#define EPS 1e-10
#define INF 1000000000

#define PREDIACTE(t, a) [](const t &a) -> bool
#define COMPARISON_T(t) bool (*)(const t &, const t &)
#define COMPARISON(t, a, b) [](const t &a, const t &b) -> bool

//// algorithm ////

// compare
template <class InIt1, class InIt2>
int partial_compare(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2) {
  return lexicographical_compare(first1, last1, first2, last2)   ? -1
         : lexicographical_compare(first2, last2, first1, last1) ? 1
                                                                 : 0;
}

// index_of
template <class InIt, class T>
inline int index_of(InIt first1, InIt last1, const T &val) {
  InIt f = find(first1, last1, val);
  return f != last1 ? distance(f, first1) : -1;
}

// C# BinarySearch風のindex_of
template <class InIt, class T>
inline int bindex_of(InIt first1, InIt last1, const T &val) {
  auto it = lower_bound(first1, last1, val);
  if (it == last1) {
    return ~distance(it, first1);
  } else if (*it == val) {
    return distance(it, first1);
  } else
    return ~distance(it, first1);
}

// vector iota iterator
vector<int> iotav(int begin, int end) {
  vector<int> r(end - begin);
  iota(allof(r), begin);
  return r;
}

struct iotait {
  int n;
  iotait(int n = 0) : n(n) {}
  iotait &operator++() {
    ++n;
    return *this;
  }
  int operator*() { return n; }
};

// 最大公約数
long gcd(long a, long b) { return b ? gcd(b, a % b) : a; }

// 最小公倍数
long lcm(long a, long b) { return a / gcd(a, b) * b; }

// 拡張ユークリッド互除法
void exgcd(long a, long b, long &x, long &y) {
  if (b != 0) {
    exgcd(b, a % b, y, x);
    y -= a / b * x;
  } else {
    x = 1;
    y = 0;
  }
}

//// data structure ////

/// 2分セグメント木。RMQとかが解ける。
template <class T = int, class TParentFunc = const T &(*)(const T &, const T &)>
struct SegTree {
  int count;
  vector<T> tree;
  TParentFunc parent;

  SegTree(int size, TParentFunc parentBuilder = std::min, T initialFill = INF)
      : count((size | size - 1) + 1), tree(count * 2), parent(parentBuilder) {
    fill(partof(tree, count, count), initialFill);
    rebuild();
  }

  // []を使うと更新されないのでrebuildすること。数が少なければupdateの方がよい。
  T &operator[](int i) { return tree[i + count]; }
  void rebuild() {
    RREP(i, count) { tree[i] = parent(tree[i * 2], tree[i * 2 + 1]); }
  }

  void update(int index, T value) {
    tree[index + count] = value;
    for (int i = (index + count) / 2; i > 0; i /= 2)
      tree[i] = parent(tree[i * 2], tree[i * 2 + 1]);
  }

  T query(int s, int e, int i, int l, int r, T value) {
    if (r <= s || e <= l)
      return value;
    if (s <= l && r <= e)
      return parent(value, tree[i]);
    value = query(s, e, i * 2, l, (l + r) / 2, value);
    value = query(s, e, i * 2 + 1, (l + r) / 2, r, value);
    return value;
  }

  T query(int start, int count, T initialValue) {
    return query(start, start + count, 1, 0, count, initialValue);
  }
};

//// prime ////
vector<unsigned char> isPrime;
vector<int> primes;
void initPrimes(int n) {
  isPrime = vector<unsigned char>(n + 1, true);
  isPrime[0] = isPrime[1] = false;
  FOR(i, 2, n + 1) {
    if (!isPrime[i])
      continue;
    primes.push_back(i);
    for (int j = i * 2; j <= n; j += i)
      isPrime[j] = false;
  }
}

//// Probability ////

// パスカルの三角形(二項定理) 2種類の並べ替えにつかう。
vector<vector<double>> makePascalTriangle(int n, bool probability = false) {
  typedef vector<double> VD;
  vector<VD> t;
  if (!t.size()) {
    t.push_back(VD(1, 1));
  }
  FOR(i, t.size(), n + 1) {
    t.push_back(VD(i + 1));
    REP(j, i) {
      double x = t[i - 1][j] * (probability ? 0.5 : 1);
      t[i][j] += x;
      t[i][j + 1] += x;
    }
  }
  return t;
}

//// geo ////

/// 3次元
struct P3 {
  double x, y, z;
  P3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
  P3 operator+() const { return *this; }
  P3 operator+(const P3 &_) const { return P3(x + _.x, y + _.y, z + _.z); }
  P3 operator-() const { return P3(-x, -y, -z); }
  P3 operator-(const P3 &_) const { return *this + -_; }
  P3 operator*(double _) const { return P3(x * _, y * _, z * _); }
  P3 operator/(double _) const { return P3(x / _, y / _, z / _); }
  double dot(const P3 &_) const { return x * _.x + y * _.y + z * _.z; } // 内積
  P3 cross(const P3 &_) const {
    return P3(y * _.z - z * _.y, z * _.x - x * _.z, x * _.y - y * _.x);
  }                                                         // 外積
  double sqlength() const { return x * x + y * y + z * z; } // 二乗長さ
  double length() const { return sqrt(sqlength()); }        // 長さ
  P3 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream &operator>>(istream &in, P3 &p) {
  in >> p.x >> p.y >> p.z;
  return in;
}
inline double abs(P3 p) { return p.length(); }

struct Sphere {
  P3 c;
  double r;
  Sphere(double x, double y, double z, double r) : c(x, y, z), r(r) {}
  Sphere(P3 c, double r) : c(c), r(r) {}
  bool IntersectWith(const Sphere &rhs) const {
    return abs(c - rhs.c) - (r + rhs.r) < EPS;
  } // 接してても真。
};
inline istream &operator>>(istream &in, Sphere &c) {
  in >> c.c >> c.r;
  return in;
}

/// 2次元
struct P2 {
  double x, y;
  P2(double x = 0, double y = 0) : x(x), y(y) {}
  P2(complex<double> c) : x(c.real()), y(c.imag()) {}
  P2 operator+() const { return *this; }
  P2 operator+(const P2 &_) const { return P2(x + _.x, y + _.y); }
  P2 operator-() const { return P2(-x, -y); }
  P2 operator-(const P2 &_) const { return *this + -_; }
  P2 operator*(double _) const { return P2(x * _, y * _); }
  P2 operator/(double _) const { return P2(x / _, y / _); }
  double dot(const P2 &_) const { return x * _.x + y * _.y; }   // 内積
  double cross(const P2 &_) const { return x * _.y - y * _.x; } // 外積
  double sqlength() const { return x * x + y * y; }             // 二乗長さ
  double length() const { return sqrt(sqlength()); }            // 長さ
  P2 orthogonal() const { return P2(y, -x); }
  P2 direction() const { return *this / length(); } // 方向ベクトル
};
inline istream &operator>>(istream &in, P2 &p) {
  in >> p.x >> p.y;
  return in;
}
inline double abs(P2 p2) { return p2.length(); }
inline P2 orthogonal(P2 p) { return p.orthogonal(); }
inline complex<double> orthogonal(complex<double> c) {
  return c * complex<double>(0, 1);
}

// a,b から ちょうど d だけ離れた点。aとbを円周に持つ円の半径。
inline pair<P2, P2> get_same_distance_points(P2 a, P2 b, double d) {
  assert(abs(a - b) <= 2 * d + EPS);
  auto v = (a + b) / 2.0 - a; // a から aとbの中点
  auto vl = abs(v);
  auto wl = sqrt(d * d - vl * vl);    // 直行Vの大きさ
  auto w = orthogonal(v) * (wl / vl); // 直行V
  return make_pair(a + v + w, a + v - w);
}

struct Circle {
  P2 c;
  double r;
  Circle(double x, double y, double r) : c(x, y), r(r) {}
  Circle(P2 c, double r) : c(c), r(r) {}
  bool IntersectWith(const Circle &rhs) const {
    return abs(c - rhs.c) - (r + rhs.r) < EPS;
  } // 接してても真。
  bool Contains(const P2 &p) const {
    return abs(p - c) - r < EPS;
  } // 接してても真。
};
inline istream &operator>>(istream &in, Circle &c) {
  in >> c.c >> c.r;
  return in;
}

//// bit ////
#ifdef _MSC_VER
#pragma push_macro("long")
#undef long
inline unsigned __builtin_ctz(unsigned x) {
  unsigned long r;
  _BitScanForward(&r, x);
  return r;
}
#pragma pop_macro("long")
#endif

inline int next_bit_permutation(int x) {
  int t = x | (x - 1);
  return (t + 1) | (unsigned)((~t & -~t) - 1) >> (__builtin_ctz(x) + 1);
}

// x の p1からlen bitと p2 から len bit を入れ替える
template <class T> int bit_swap(T x, size_t p1, size_t p2, size_t len) {
  T mask = (1ul << len) - 1;
  T ope = (x >> p1 ^ x >> p2) & mask; // 入れ替える場所のxorを求める
  return x ^ (ope << p1 | ope << p2); // 入れ替える場所をxor。
}

//// graph ////
struct Path {
  int from;
  int to;
  double cost;
  double capacity;
  Path(int from = 0, int to = 0, double cost = 0, double capacity = -1)
      : from(from), to(to), cost(cost), capacity(capacity) {}
  bool operator<(const Path &rhs) const { return cost < rhs.cost; }
  bool operator>(const Path &rhs) const { return cost > rhs.cost; }
};

// prim //
pair<double, vector<int>> prim(const vector<vector<double>> &costTable) {
  int N = costTable.size();
  priority_queue<Path, vector<Path>, greater<Path>> q;
  q.push(Path(0, 0, 0));

  vector<int> parent(N, -1);
  double totalCost = 0;
  while (!q.empty()) {
    Path cur = q.top();
    q.pop();
    int i = cur.to;
    if (parent[i] != -1)
      continue;
    parent[i] = cur.from;
    totalCost += cur.cost;
    REP(j, N) if (parent[j] == -1) q.push(Path(i, j, costTable[i][j]));
  }
  return make_pair(totalCost, parent);
}

// dijkstra //
pair<vector<double>, vector<int>> dijkstra(const vector<vector<Path>> &routes,
                                           int start = 0, int goal = -1) {
  int N = routes.size();
  priority_queue<Path, vector<Path>, greater<Path>> q;
  q.push(Path(start, start, 0));

  vector<int> prev(N, -1);
  vector<double> cost(N, INF);
  while (!q.empty()) {
    Path cur = q.top();
    q.pop();
    int i = cur.to;
    if (prev[i] != -1)
      continue;
    prev[i] = cur.from;
    cost[i] = cur.cost;
    if (i == goal) {
      break;
    }
    REP(j, routes[i].size()) {
      Path next = Path(i, routes[i][j].to, cur.cost + routes[i][j].cost);
      if (prev[next.to] == -1)
        q.push(next);
    }
  }
  return make_pair(cost, prev);
}

//// dice ////

// さいころ
template <class T> struct Die {
  /* v as 天一地六東五西二南三北四
  |3|
  |1|0|4|5|
  |2|
  */
  T v[6];

  void rt(int x, int y, int z, int w) {
    swap(v[x], v[y]);
    swap(v[x], v[z]);
    swap(v[x], v[w]);
  }
  void rotateLeft() { rt(0, 4, 5, 1); }
  void rotateRight() { rt(1, 5, 4, 0); }
  void rotateDown() { rt(0, 3, 5, 2); }
  void rotateUp() { rt(2, 5, 3, 0); }
  void rotateCw() { rt(3, 1, 2, 4); }
  void rotateCcw() { rt(4, 2, 1, 3); }
  bool operator<(const Die &rhs) const {
    return lexicographical_compare(aallof(v), aallof(rhs.v));
  }
  bool operator==(const Die &rhs) const { return equal(aallof(v), rhs.v); }
  bool operator!=(const Die &rhs) const { return !equal(aallof(v), rhs.v); }
};

// 8面体
template <class T> struct Octahedra {
  /* v as
  /0\\/1\\/2\\/3\\
  \\4/\\5/\\6/\\7/
  */
  T v[8];

  void rt(int x, int y, int z, int w) {
    swap(v[x], v[y]);
    swap(v[x], v[z]);
    swap(v[x], v[w]);
  }
  void rotateLeft() {
    rt(0, 1, 2, 3);
    rt(4, 5, 6, 7);
  }
  void rotateRight() {
    rt(3, 2, 1, 0);
    rt(7, 6, 5, 4);
  }
  void rotateDown() {
    rt(0, 4, 7, 3);
    rt(1, 5, 6, 2);
  }
  void rotateUp() {
    rt(3, 7, 4, 0);
    rt(2, 6, 5, 2);
  }
  void rotateCw() {
    rt(0, 1, 5, 4);
    rt(3, 2, 6, 7);
  }
  void rotateCcw() {
    rt(4, 5, 1, 0);
    rt(7, 6, 1, 3);
  }
  bool operator<(const Octahedra &rhs) const {
    return lexicographical_compare(aallof(v), aallof(rhs.v));
  }
  bool operator==(const Octahedra &rhs) const {
    return equal(aallof(v), rhs.v);
  }
  bool operator!=(const Octahedra &rhs) const {
    return !equal(aallof(v), rhs.v);
  }
};

//// i/o ////
template <class T> class vevector : public vector<vector<T>> {
public:
  vevector(int n = 0, int m = 0) : vector<vector<T>>(n, vector<T>(m)){};
  vevector(int n, int m, const T &initial)
      : vector<vector<T>>(n, vector<T>(m, initial)){};
};

template <class T> T read() {
  T t;
  cin >> t;
  return t;
}
template <class T> vector<T> read(int n) {
  vector<T> v;
  REP(i, n) { v.push_back(read<T>()); }
  return v;
}
template <class T> vevector<T> read(int n, int m) {
  vevector<T> v;
  REP(i, n) v.push_back(read<T>(m));
  return v;
}
template <class T> vevector<T> readjag(int n) {
  vevector<T> v;
  REP(i, n) v.push_back(read<T>(read<int>()));
  return v;
}
struct _Reader {
  template <class T> _Reader operator,(T &rhs) {
    cin >> rhs;
    return *this;
  }
};
#define READ(t, ...)                                                           \\
  t __VA_ARGS__;                                                               \\
  _Reader(), __VA_ARGS__

template <class T> void write(const T &t) { cout << t << endl; }
template <class T, class T2> void write(const T &t, const T2 &t2) {
  cout << t << ' ' << t2 << endl;
}
template <class T> void write(const vector<T> &v) {
  ostringstream ss;
  for (auto x : v)
    ss << x << ' ';
  auto s = ss.str();
  cout << s.substr(0, s.length() - 1) << endl;
}

//// start up ////
void solve();
int main() {
  // freopen("A.in", "r", stdin);
  solve();
  return 0;
}

////////////////////
/// template end ///
////////////////////

#define MOD 1000000007

int dfs(const vector<int> &we, const vector<int> &wsum,
        vector<vevector<int>> &memo, int cur, int weight, int weLastSkiped,
        vector<int> &dbg) {
  if (cur == -1) {
    if (weight >= we[weLastSkiped]) {
      return 0;
    } // とらなくてはいけないアイテムをとってない。
    // write(dbg);
    return 1;
  }

  if (memo[cur][weight][weLastSkiped] != -1) {
    return memo[cur][weight][weLastSkiped];
  }

  // のこりのアイテムをすべてとっても、かばんに余裕ができてしまう。
  if (we[weLastSkiped] + wsum[cur] <= weight) {
    memo[cur][weight][weLastSkiped] = 0;
    return 0;
  }

  int pat = 0;
  // かばんにはいる
  if (weight >= we[cur]) {
    dbg.push_back(we[cur]);
    pat += dfs(we, wsum, memo, cur - 1, weight - we[cur], weLastSkiped, dbg);
    dbg.pop_back();
  }

  // かばんにいれない
  { pat += dfs(we, wsum, memo, cur - 1, weight, cur, dbg); }

  return memo[cur][weight][weLastSkiped] = pat % MOD;
}

void solve() {
  auto testcases = INF; // read<int>();
  REP(testcase, testcases) {
    READ(int, n, w);
    auto we = read<int>(n);
    we.push_back(INF);
    n++;
    sort(allof(we));

    auto wesum = vector<int>();
    partial_sum(allof(we), back_inserter(wesum));

    vector<vevector<int>> memo(n + 1, vevector<int>(w + 1, n + 1, -1));
    auto dbg = vector<int>();
    int ret = dfs(we, wesum, memo, n - 2, w, n - 1, dbg);
    write(ret);

    break;
  }
}