#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5;
ll n, t;
int a[N], b[N];
using D = double;
D p[N];
template <class T = long long, class Comp = less<T> >
struct DynamicCHT {
  static T INF;
  static T EPS;
  static Comp comp;

 private:
  struct Line {
    T a, b;
    Line(const T &a, const T &b) : a(a), b(b) {}
    bool operator<(const Line &rhs) const {
      return a != rhs.a ? comp(rhs.a, a) : comp(b, rhs.b);
    }
  };
  struct CP {
    T numer, denom;
    Line p;
    CP(const T &n) : numer(n), denom(1), p(0, 0) {}
    CP(const Line &p1, const Line &p2) : p(p2) {
      if (p1.a == INF || p1.a == -INF)
        numer = -INF, denom = 1;
      else if (p2.a == INF || p2.a == -INF)
        numer = INF, denom = 1;
      else {
        numer = p1.b - p2.b, denom = p2.a - p1.a;
        if (denom < 0) numer = -numer, denom = -denom;
      }
    }
    bool operator<(const CP &rhs) const {
      if (numer == INF || rhs.numer == -INF) return 0;
      if (numer == -INF || rhs.numer == INF) return 1;
      return numer * rhs.denom < rhs.numer * denom;
    }
  };
  set<Line> lines;
  set<CP> cps;

 public:
  DynamicCHT() {
    lines.insert({Line(INF, 0), Line(-INF, 0)});
    cps.insert(CP(Line(INF, 0), Line(-INF, 0)));
  }
  void add(const T &a, const T &b) {
    const Line p(a, b);
    typename set<Line>::iterator pos = lines.insert(p).first;
    if (check(*prev(pos), p, *next(pos))) {
      lines.erase(pos);
      return;
    }
    cps.erase(CP(*prev(pos), *next(pos)));
    {
      typename set<Line>::iterator it = prev(pos);
      while (it != lines.begin() && check(*prev(it), *it, p)) --it;
      eraseRange(it, prev(pos));
      lines.erase(++it, pos);
      pos = lines.find(p);
    }
    {
      typename set<Line>::iterator it = next(pos);
      while (next(it) != lines.end() && check(p, *it, *next(it))) ++it;
      eraseRange(++pos, it);
      lines.erase(pos, it);
      pos = lines.find(p);
    }
    cps.insert(CP(*prev(pos), *pos));
    cps.insert(CP(*pos, *next(pos)));
  }
  T query(const T &x) const {
    const Line &p = (--cps.lower_bound(CP(x)))->p;
    return p.a * x + p.b;
  }
  tuple<T, T> get(const T &x) const {
    const Line &p = (--cps.lower_bound(CP(x)))->p;
    return make_tuple(p.a, p.b);
  }
  friend ostream &operator<<(ostream &os, const DynamicCHT &a) {
    os << "\n";
    os << "lines : " << a.lines.size() << "\n";
    for (auto &p : a.lines)
      os << "(" << p.a << ", " << p.b << ")"
         << "\n";
    os << "cross points : " << a.cps.size() << "\n";
    for (auto &p : a.cps)
      os << "(x = " << p.numer << "/" << p.denom << "; " << p.p.a << ", "
         << p.p.b << ")"
         << "\n";
    return os;
  }

 private:
  void eraseRange(typename set<Line>::iterator a,
                  typename set<Line>::iterator b) {
    for (typename set<Line>::iterator it = a; it != b; ++it)
      cps.erase(CP(*it, *next(it)));
  }
  bool check(const Line &p1, const Line &p2, const Line &p3) {
    if (p1.a == p2.a) return 1;
    if (p1.a == INF || p1.a == -INF || p3.a == INF || p3.a == -INF) return 0;
    return (p2.a - p1.a) * (p3.b - p2.b) + EPS >= (p2.b - p1.b) * (p3.a - p2.a);
  }
};
template <class T, class Comp>
T DynamicCHT<T, Comp>::INF = numeric_limits<T>::has_infinity
                                 ? numeric_limits<T>::infinity()
                                 : numeric_limits<T>::max();
template <class T, class Comp>
T DynamicCHT<T, Comp>::EPS = 1e-19;
template <class T, class Comp>
Comp DynamicCHT<T, Comp>::comp = Comp();
template <class T>
vector<vector<T> > mult(vector<vector<T> > a, vector<vector<T> > b) {
  assert(a[0].size() == b.size());
  vector<vector<T> > res(a.size(), vector<T>(b[0].size(), 0));
  for (size_t i = 0; i < a.size(); i++) {
    for (size_t j = 0; j < b[0].size(); j++) {
      for (size_t k = 0; k < b.size(); k++) {
        res[i][j] += a[i][k] * b[k][j];
      }
    }
  }
  return res;
}
template <class T>
vector<vector<T> > makeE(int n) {
  vector<vector<T> > r(n, vector<T>(n, 0));
  for (int i = 0; i < n; i++) r[i][i] = T(1);
  return r;
}
template <class T>
vector<vector<T> > pow(vector<vector<T> > a, ll k) {
  assert(a.size() == a[0].size());
  vector<vector<T> > r = makeE<T>(a.size());
  while (k) {
    if (k & 1) r = mult(r, a);
    a = mult(a, a);
    k >>= 1;
  }
  return r;
}
using Vec = vector<D>;
using Mat = vector<Vec>;
int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  cin >> n >> t;
  D m = 0;
  DynamicCHT<D, greater<D> > cht;
  for (int i = 0; i < n; i++) {
    cin >> a[i] >> b[i] >> p[i];
    m = max(m, b[i] * p[i]);
    cht.add(p[i], p[i] * a[i]);
  }
  cout << fixed << setprecision(12);
  ll le = 1;
  Mat v{{cht.query(0)}, {1}, {1}};
  while (le != t) {
    D xle = m * le - v[0][0];
    auto g = cht.get(xle);
    ll f = t - le;
    ll h = 1;
    vector<Mat> mats;
    Mat A(3, Vec(3));
    A[0][0] = 1 - get<0>(g);
    A[0][1] = get<0>(g) * m;
    A[0][2] = get<1>(g);
    A[1][1] = A[1][2] = A[2][2] = 1;
    mats.push_back(A);
    while ((1ll << h) - 1 < f) {
      A = mult(A, A);
      mats.push_back(A);
      h++;
    }
    ll now = 0;
    for (int k = h - 1; k >= 0; k--) {
      ll j = 1ll << k;
      if (now + j > f) continue;
      auto tv = mult(mats[k], v);
      auto tdp = tv[0][0];
      ll tt = le + now + j;
      D x = m * tt - tdp;
      if (g == cht.get(x)) {
        v = tv;
        now += j;
      }
    }
    if (now + 1 <= f) {
      v = mult(mats[0], v);
      now++;
    }
    le += now;
  }
  cout << v[0][0] << endl;
  return 0;
}
