#include "bits/stdc++.h"
using namespace std;

// fundamental
using ll = long long;
#define REP(i,n) for (ll i = 0; i < (n); ++i)
#define FOR(i,s,n) for (ll i = (s); i < (n); ++i)
#define ALL(c) (c).begin(), (c).end()
#define TEN(x) ((ll)1e##x)
#define MAXC(c,x) (c = max(c, x))
#define MINC(c,x) (c = min(c, x))
const ll mod = TEN(9) + 7;

// vector
using vl = vector<ll>; using vvl = vector<vl>; using vvvl = vector<vvl>;
template<class T, size_t N, class A = size_t> auto mdv(A size = 0) -> typename enable_if<N==1, vector<T>>::type { return vector<T>(size); }
template<class T, size_t N, class A = size_t> auto mdv(A size = 0) -> vector<decltype(mdv<T, N - 1>())> { return vector<decltype(mdv<T, N - 1>())>(size); }
template<class T, size_t N, class A, class... B> auto mdv(A size, B... rest) -> typename enable_if<N!=1, vector<decltype(mdv<T, N - 1>(rest...))>>::type { return vector<decltype(mdv<T, N - 1>(rest...))>(size, mdv<T, N - 1>(rest...)); }
template<class T, class... A> auto mdv(A... size) -> decltype(mdv<T, sizeof...(size), A...>(size...)) { return mdv<T, sizeof...(size), A...>(size...); }
// template<size_t N, class A, class... B> auto mdvl(A size, B... rest) -> decltype(mdv<N, ll, A, B...>(size, rest...)) { return mdv<N, ll, A, B...>(size, rest...); }

// template<class T, class A> auto mdv(A size) -> vector<T> { return vector<T>(size); }
// template<class T, class A, class... B> auto mdv(A size, B... rest) -> vector<decltype(mdv<T>(rest...))> { return vector<decltype(mdv<T>(rest...))>(size, mdv<T>(rest...)); }

// io
template<class T> istream& operator >>(istream& is, vector<T>& vec){ for(T& x: vec) is >> x; return is; }
template<class T, class U> istream& operator >>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return is; }
template<class T> void input(T& t) { cin >> t; assert(cin); } template<class T, class... Ts> void input(T& t, Ts&... ts) { cin >> t; input(ts...); }
template<class T> void print(T&& t) { cout << t; } template<class T, class... Ts> void print(T&& t, Ts&&... ts) { cout << t; print(ts...); }
template<class T> void println(T&& t) { cout << t << endl; } template<class T, class... Ts> void println(T&& t, Ts&&... ts) { cout << t; println(ts...); }
template<class T> string join(const vector<T>& v, const string & sep) { stringstream ss; REP(i, v.size()) ss << (i != 0 ? sep : "") << v[i]; return ss.str(); }

// Segment Tree : 時間計算量 O(n log n), 空間計算量 O(n)
// require  : なし
// verified : 
//
// T はモノイド（単位元を持ち，結合則が成り立つ）であることが要求される
template <class T, class U = size_t>
struct SegTree {
	// !!! 実装時 t(lhs, rhs) の引数の順番に注意(意図せず可換則が要求されてしまう) !!!
	typedef typename T::V V;
	explicit SegTree(U _n = 0, const T &t = T()) : n(1), t(t) {
		while (n < _n) n *= 2;
		v.assign(n * 2 - 1, t.identity());
		if (n >= 2) {
			for (U i = n - 2;; --i) {
				v[i] = t(v[i * 2 + 1], v[i * 2 + 2]);
				if (i == 0) break; // Uが符号無し整数の可能性がある為こう実装している
			}
		}
	}
	V operator[](U i) const { return v[n - 1 + i]; }
	void set(U i, const V & x) {
		i += n - 1;
		v[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			v[i] = t(v[i * 2 + 1], v[i * 2 + 2]);
		}
	}
	// [a,b)の範囲についてのクエリを返す
	V get(U a, U b) const { return q(a, b, 0, 0, n); }

	// f(get(0, i), x) == trueを満たす最小のiを返す
	// f(get(i, n), x) == trueを満たす最大のiを返す場合はrev:のところを書き換える(未verify)．
	template<class F>
	U lower_bound(const V & x, F && f) const { return lb(x, t.identity(), 0, 0, n, f); }

	// f(get(l, i), x) == trueを満たす最小のiを返す
	// f(get(i, l), x) == trueを満たす最大のiを返す場合はrev:のところを書き換える(未verify)．
	// 木をジグザグに登っていったあとlb()で下っていくイメージ
	template<class F>
	U lower_bound(const V & x, U l, F && f) const {
		// rev: l--;
		U k = l + n - 1, len = 1;
		V nlv = v[k], lv = t.identity();
		while (!f(nlv, x)) {
			while (k % 2 == 0) {      // rev: k % 2 == 1
				if (k == 0) return 0; // rev: return n;
				k = (k - 1) / 2;
				l -= len; // rev: delete
				len *= 2;
			}
			k += 1;   // rev: k -= 1;
			l += len; // rev: l -= len;
			lv = nlv;
			nlv = t(nlv, v[k]); // rev: t(v[k], nlv)
		}
		return lb(x, lv, k, l, l + len, f);
	}
private:
	// t : traits のインスタンス
	// v : 完全二分木の配列表現
	// n : 完全二分木の葉の数
	T t;
	vector<V> v;
	U n;

	// [a,b)の範囲についてのクエリを返す
	// k     : 現在見ている接点の番号
	// [l,r) : kに対応した範囲 
	V q(U a, U b, U k, U l, U r) const {
		if (r <= a || b <= l) return t.identity(); // 範囲外
		if (a <= l && r <= b) return v[k];         // [l,r) ⊂ [a,b)

		//[l,r)の一部が[a,b)に含まれる
		U c = (l + r) / 2;
		return t(
			q(a, b, k * 2 + 1, l, c),
			q(a, b, k * 2 + 2, c, r)
		);
	}

	template<class F>
	U lb(const V & x, const V & lv, U k, U l, U r, F && f) const {
		if (k >= n - 1) return f(t(lv, v[k]), x) ? r : 0; // rev: f(t(v[k], lv), x) ? l : n
		V nlv = t(lv, v[k * 2 + 1]); // rev: t(v[k * 2 + 2], lv);
		U c = (l + r) / 2;
		return f(nlv, x) ? lb(x, lv,  2 * k + 1, l, c, f)  // rev: lb(x,  lv, 2 * k + 2, c, r, f);
		                 : lb(x, nlv, 2 * k + 2, c, r, f); // rev: lb(x, nlv, 2 * k + 1, l, c, f);
	}
};

template <class T>
struct LCMTrait{
	typedef T V;
	V identity() const { return 1; }
	V operator()(const V &a, const V &b) const { return lcm(a, b); }
};

template <class T>
struct MinTrait{
	typedef T V;
	V identity() const { return TEN(10); }
	V operator()(const V &a, const V &b) const { return min(a, b); }
};

template <class T>
struct MaxTrait{
	typedef T V;
	V identity() const { return 0; }
	V operator()(const V &a, const V &b) const { return max(a, b); }
};

template <class T>
struct SumTrait{
	typedef T V;
	V identity() const { return 0; }
	V operator()(const V &a, const V &b) const { return a + b; }
};

// 制約fを満たす最大値（最小値）の二分探索
// ok < ng なら最大値，ok > ng なら最小値探索になる
template<typename F> ll bsearch(ll ok, ll ng, F f) {
  while (abs(ok - ng) > 1) {
    ll middle = (ok + ng) / 2;
    (f(middle) ? ok : ng) = middle;
  }
  return ok;
}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(50);

    ll n,x; cin >>n >> x;
    vl b(n), l(n), u(n);
    REP(i, n) cin >> b[i] >> l[i] >> u[i];
    vector<pair<ll,ll>> p;
    REP(i, n) p.push_back(make_pair((x - b[i]) * u[i] + l[i] * b[i], i));
    sort(ALL(p));
    reverse(ALL(p));

    SegTree<SumTrait<ll>> st(n);
    REP(i, n) st.set(i, p[i].first);

    ll sum = 0;
    REP(i, n) sum += l[i] * b[i];
    ll ans = TEN(10);
    REP(i, n) {
        st.set(i, 0);
        ll idx = bsearch(0, n, [&](ll j){
            return st.get(0, j) < sum;
        });
        ll rest = sum - st.get(0, idx);
        
        ll cnt = idx;
        if (i < idx) cnt--;
        cnt *= x;

        ll j = p[i].second;
        if (rest <= l[j] * b[j]) {
            ans = min(ans, cnt + rest / l[j] + (rest % l[j] != 0));
        } else if (rest <= p[i].first) {
            rest -= l[j] * b[j];
            cnt += b[j];
            ans = min(ans, cnt + rest / u[j] + (rest % u[j] != 0));
        }
        st.set(i, p[i].first);
    }
    cout << ans << endl;
}


Measured memory_bytes: 6384