Problem: An infinitely long Line Chillland Collider (LCC) was built in Chillland. There are n pipes with coordinates x_i that are connected to LCC. When the experiment starts at time 0, i-th proton flies from the i-th pipe with speed v_i. It flies to the right with probability p_i and flies to the left with probability (1 - p_i). The duration of the experiment is determined as the time of the first collision of any two protons. In case there is no collision, the duration of the experiment is considered to be zero.

Find the expected value of the duration of the experiment.

<image>Illustration for the first example

Input

The first line of input contains one integer n — the number of pipes (1 ≤ n ≤ 10^5). Each of the following n lines contains three integers x_i, v_i, p_i — the coordinate of the i-th pipe, the speed of the i-th proton and the probability that the i-th proton flies to the right in percentage points (-10^9 ≤ x_i ≤ 10^9, 1 ≤ v ≤ 10^6, 0 ≤ p_i ≤ 100). It is guaranteed that all x_i are distinct and sorted in increasing order.

Output

It's possible to prove that the answer can always be represented as a fraction P/Q, where P is an integer and Q is a natural number not divisible by 998 244 353. In this case, print P ⋅ Q^{-1} modulo 998 244 353.

Examples

Input


2
1 1 100
3 1 0


Output


1


Input


3
7 10 0
9 4 86
14 5 100


Output


0


Input


4
6 4 50
11 25 50
13 16 50
15 8 50


Output


150902884

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
namespace IO {
const int BUFFER_SIZE = 1 << 15;
char input_buffer[BUFFER_SIZE];
int input_pos = 0, input_len = 0;
void _update_input_buffer() {
  input_len = fread(input_buffer, sizeof(char), BUFFER_SIZE, stdin);
  input_pos = 0;
  if (input_len == 0) input_buffer[0] = EOF;
}
inline char next_char(bool advance = true) {
  if (input_pos >= input_len) _update_input_buffer();
  return input_buffer[advance ? input_pos++ : input_pos];
}
template <typename T>
inline void read_int(T &number) {
  bool negative = false;
  number = 0;
  while (!isdigit(next_char(false)))
    if (next_char() == '-') negative = true;
  do {
    number = 10 * number + (next_char() - '0');
  } while (isdigit(next_char(false)));
  if (negative) number = -number;
}
template <typename T, typename... Args>
inline void read_int(T &number, Args &...args) {
  read_int(number);
  read_int(args...);
}
}  // namespace IO
const int MOD = 998244353;
struct mod_int {
  int val;
  mod_int(long long v = 0) {
    if (v < 0) v = v % MOD + MOD;
    if (v >= MOD) v %= MOD;
    val = v;
  }
  static int mod_inv(int a, int m = MOD) {
    int g = m, r = a, x = 0, y = 1;
    while (r != 0) {
      int q = g / r;
      g %= r;
      swap(g, r);
      x -= q * y;
      swap(x, y);
    }
    return x < 0 ? x + m : x;
  }
  explicit operator int() const { return val; }
  mod_int &operator+=(const mod_int &other) {
    val += other.val;
    if (val >= MOD) val -= MOD;
    return *this;
  }
  mod_int &operator-=(const mod_int &other) {
    val -= other.val;
    if (val < 0) val += MOD;
    return *this;
  }
  static unsigned fast_mod(uint64_t x, unsigned m = MOD) {
    return x % m;
    unsigned x_high = x >> 32, x_low = (unsigned)x;
    unsigned quot, rem;
    asm("divl %4\n" : "=a"(quot), "=d"(rem) : "d"(x_high), "a"(x_low), "r"(m));
    return rem;
  }
  mod_int &operator*=(const mod_int &other) {
    val = fast_mod((uint64_t)val * other.val);
    return *this;
  }
  mod_int &operator/=(const mod_int &other) { return *this *= other.inv(); }
  friend mod_int operator+(const mod_int &a, const mod_int &b) {
    return mod_int(a) += b;
  }
  friend mod_int operator-(const mod_int &a, const mod_int &b) {
    return mod_int(a) -= b;
  }
  friend mod_int operator*(const mod_int &a, const mod_int &b) {
    return mod_int(a) *= b;
  }
  friend mod_int operator/(const mod_int &a, const mod_int &b) {
    return mod_int(a) /= b;
  }
  mod_int &operator++() {
    val = val == MOD - 1 ? 0 : val + 1;
    return *this;
  }
  mod_int &operator--() {
    val = val == 0 ? MOD - 1 : val - 1;
    return *this;
  }
  mod_int operator++(int) {
    mod_int before = *this;
    ++*this;
    return before;
  }
  mod_int operator--(int) {
    mod_int before = *this;
    --*this;
    return before;
  }
  mod_int operator-() const { return val == 0 ? 0 : MOD - val; }
  bool operator==(const mod_int &other) const { return val == other.val; }
  bool operator!=(const mod_int &other) const { return val != other.val; }
  mod_int inv() const { return mod_inv(val); }
  mod_int pow(long long p) const {
    assert(p >= 0);
    mod_int a = *this, result = 1;
    while (p > 0) {
      if (p & 1) result *= a;
      a *= a;
      p >>= 1;
    }
    return result;
  }
  friend ostream &operator<<(ostream &stream, const mod_int &m) {
    return stream << m.val;
  }
};
struct mod_matrix_fixed_size {
  static const int SIZE = 2;
  mod_int values[SIZE][SIZE];
  mod_matrix_fixed_size() {
    for (int i = 0; i < SIZE; i++)
      for (int j = 0; j < SIZE; j++) values[i][j] = 0;
  }
  mod_matrix_fixed_size(const vector<vector<mod_int>> &v) {
    for (int i = 0; i < SIZE; i++)
      for (int j = 0; j < SIZE; j++) values[i][j] = v[i][j];
  }
  mod_int *operator[](int index) { return values[index]; }
  const mod_int *operator[](int index) const { return values[index]; }
  void make_identity() {
    for (int i = 0; i < SIZE; i++)
      for (int j = 0; j < SIZE; j++) values[i][j] = i == j ? 1 : 0;
  }
  mod_matrix_fixed_size operator*(const mod_matrix_fixed_size &other) const {
    mod_matrix_fixed_size product;
    for (int i = 0; i < SIZE; i++)
      for (int j = 0; j < SIZE; j++)
        if (values[i][j] != 0)
          for (int k = 0; k < SIZE; k++)
            product[i][k] += values[i][j] * other[j][k];
    return product;
  }
  mod_matrix_fixed_size &operator*=(const mod_matrix_fixed_size &other) {
    return *this = *this * other;
  }
  mod_matrix_fixed_size power(long long p) const {
    assert(p >= 0);
    mod_matrix_fixed_size m = *this;
    mod_matrix_fixed_size result;
    result.make_identity();
    while (p > 0) {
      if (p & 1) result *= m;
      p >>= 1;
      if (p > 0) m *= m;
    }
    return result;
  }
  void print() const {
    for (int i = 0; i < SIZE; i++)
      for (int j = 0; j < SIZE; j++)
        cout << values[i][j] << (j < SIZE - 1 ? ' ' : '\n');
  }
};
struct segment {
  mod_matrix_fixed_size m;
  segment(mod_int m00 = 1, mod_int m01 = 0, mod_int m10 = 0, mod_int m11 = 1) {
    m = mod_matrix_fixed_size({{m00, m01}, {m10, m11}});
  }
  void join(const segment &other) { m *= other.m; }
  void join(const segment &a, const segment &b) { m = a.m * b.m; }
};
int right_half[32];
struct basic_seg_tree {
  static const bool POWER_OF_TWO_MODE = true;
  int tree_n = 0;
  vector<segment> tree;
  basic_seg_tree(int n = -1) {
    if (n >= 0) init(n);
  }
  void init(int n) {
    if (POWER_OF_TWO_MODE) {
      tree_n = 1;
      while (tree_n < n) tree_n *= 2;
    } else {
      tree_n = n;
    }
    tree.assign(2 * tree_n, segment());
  }
  void build(const vector<segment> &initial) {
    int n = initial.size();
    init(n);
    assert(n <= tree_n);
    for (int i = 0; i < n; i++) tree[tree_n + i] = initial[i];
    for (int position = tree_n - 1; position > 0; position--)
      tree[position].join(tree[2 * position], tree[2 * position + 1]);
  }
  segment query(int a, int b) {
    assert(0 <= a && a <= b && b <= tree_n);
    segment answer;
    int r_size = 0;
    for (a += tree_n, b += tree_n; a < b; a /= 2, b /= 2) {
      if (a & 1) answer.join(tree[a++]);
      if (b & 1) right_half[r_size++] = --b;
    }
    for (int i = r_size - 1; i >= 0; i--) answer.join(tree[right_half[i]]);
    return answer;
  }
  segment query_single(int index) {
    assert(0 <= index && index < tree_n);
    return tree[tree_n + index];
  }
  void join_up(int position) {
    while (position > 1) {
      position /= 2;
      tree[position].join(tree[2 * position], tree[2 * position + 1]);
    }
  }
  void update(int index, const segment &seg) {
    assert(0 <= index && index < tree_n);
    int position = tree_n + index;
    tree[position] = seg;
    join_up(position);
  }
};
struct event {
  long long distance = 0, velocity = 1;
  int index, row, col;
  event() {}
  event(long long _distance, long long _velocity, int _index, int _row,
        int _col)
      : distance(_distance),
        velocity(_velocity),
        index(_index),
        row(_row),
        col(_col) {
    assert(distance >= 0 && velocity > 0);
  }
  mod_int get_time() const { return mod_int(distance) / velocity; }
  bool operator<(const event &other) const {
    return distance * other.velocity < other.distance * velocity;
  }
};
int main() {
  int N;
  IO::read_int(N);
  vector<int> X(N), V(N);
  vector<mod_int> L(N), R(N);
  const mod_int INV100 = mod_int(100).inv();
  for (int i = 0; i < N; i++) {
    int P;
    IO::read_int(X[i], V[i], P);
    R[i] = P * INV100;
    L[i] = 1 - R[i];
  }
  basic_seg_tree tree(N);
  vector<segment> transitions(N);
  for (int i = 0; i < N; i++)
    transitions[i].m = mod_matrix_fixed_size({{L[i], R[i]}, {L[i], R[i]}});
  tree.build(transitions);
  auto &&get_probability = [&]() {
    return tree.tree[1].m[0][0] + tree.tree[1].m[0][1];
  };
  vector<event> events;
  for (int i = 1; i < N; i++) {
    long long distance = X[i] - X[i - 1];
    events.emplace_back(distance, V[i] + V[i - 1], i, 1, 0);
    if (V[i] > V[i - 1])
      events.emplace_back(distance, V[i] - V[i - 1], i, 0, 0);
    else if (V[i - 1] > V[i])
      events.emplace_back(distance, V[i - 1] - V[i], i, 1, 1);
  }
  sort(events.begin(), events.end());
  mod_int total = 0, previous_probability = 1;
  for (event &ev : events) {
    transitions[ev.index].m[ev.row][ev.col] = 0;
    tree.update(ev.index, transitions[ev.index]);
    mod_int time = ev.get_time();
    mod_int current_probability = get_probability();
    total += (previous_probability - current_probability) * time;
    previous_probability = current_probability;
  }
  cout << total << '\n';
}