12
-6712 6
2375 73
4643 197
-5660 215
-378 223
2228 307
3305 340
3449 468
-4389 707
-7161 729
-1838 921
-1655 985
730
 5
1 5
6 7
17127 17
17072 42
17042 77
3
 7
-976754 20479
79929143 911181
9598220 82517
-51609349 810257
67416551 266544
-14170975 307690
-15476178 491195
352
 22
-5301 602
-1400 194
-8512 987
-282 962
6484 494
9091 523
-7744 92
6002 461
5053 305
-1339 272
-821 165
9308 785
929 421
8384 883
1266 157
8411 923
-2949 885
7725 687
6859 197
-7630 867
5031 918
5662 410
41

11 12
 2 3
 5 5
 9 9

#include <bits/stdc++.h>
using namespace std;
struct Treap {
  long long key;
  int f, maxf;
  int height, s;
  int addk, addf;
  Treap *left, *right, *parent;
  Treap(long long a, int b, Treap *parent = 0) : key(a), f(b), parent(parent) {
    height = rand();
    maxf = f, s = 1;
    addk = addf = 0;
    left = right = 0;
  }
  void push() {
    if (!addk && !addf) {
      return;
    }
    if (left) {
      left->key += addk, left->f += addf, left->maxf += addf;
      left->addk += addk;
      left->addf += addf;
    }
    if (right) {
      right->key += addk, right->f += addf, right->maxf += addf;
      right->addk += addk;
      right->addf += addf;
    }
    addk = addf = 0;
  }
  void maintain() {
    maxf = f, s = 1;
    if (left) {
      maxf = std::max(maxf, left->maxf);
      s += left->s;
    }
    if (right) {
      maxf = std::max(maxf, right->maxf);
      s += right->s;
    }
  }
};
Treap *merge(Treap *x, Treap *y) {
  if (!x) return y;
  if (!y) return x;
  if (x->height < y->height) {
    x->push();
    x->right = merge(x->right, y);
    if (x->right) x->right->parent = x;
    x->maintain();
    return x;
  } else {
    y->push();
    y->left = merge(x, y->left);
    if (y->left) y->left->parent = y;
    y->maintain();
    return y;
  }
}
Treap *get_left(Treap *x) {
  if (!x) {
    return x;
  }
  if (!x->left) {
    return x;
  }
  x->push();
  return get_left(x->left);
}
Treap *get_right(Treap *x) {
  if (!x) {
    return x;
  }
  if (!x->right) {
    return x;
  }
  x->push();
  return get_right(x->right);
}
Treap *prev(Treap *cur) {
  if (cur->left) {
    return get_right(cur->left);
  } else {
    Treap *pa = cur->parent, *prev = cur;
    while (pa) {
      if (prev == pa->right)
        break;
      else
        prev = pa, pa = pa->parent;
    }
    return pa;
  }
}
Treap *next(Treap *cur) {
  if (cur->right) {
    return get_left(cur->right);
  } else {
    Treap *pa = cur->parent, *prev = cur;
    while (pa) {
      if (prev == pa->left)
        break;
      else
        prev = pa, pa = pa->parent;
    }
    return pa;
  }
}
void split(Treap *t, Treap *&l, Treap *&r, int x) {
  if (!t) {
    l = r = 0;
    return;
  }
  t->push();
  if (t->key >= x) {
    split(t->left, l, t->left, x);
    if (t->left) t->left->parent = t;
    r = t;
  } else {
    split(t->right, t->right, r, x);
    if (t->right) t->right->parent = t;
    l = t;
  }
  t->maintain();
}
Treap *access(Treap *r, int key) {
  if (!r) return r;
  if (r->key == key) return r;
  r->push();
  if (key < r->key)
    return access(r->left, key);
  else
    return access(r->right, key);
}
void insert(Treap *&r, long long key, int val) {
  Treap *ne = new Treap(key, val);
  Treap *t1, *t2;
  split(r, t1, t2, key);
  r = merge(t1, ne);
  r = merge(r, t2);
}
Treap *remove(Treap *&r, long long key) {
  Treap *x = access(r, key);
  if (x) {
    x->push();
    Treap *xx = merge(x->left, x->right);
    if (x->parent == NULL) {
      r = xx;
      if (r) r->parent = 0;
    } else {
      if (x == x->parent->left)
        x->parent->left = xx;
      else
        x->parent->right = xx;
      if (xx) xx->parent = x->parent;
    }
    Treap *tmp = x->parent;
    if (xx) xx->maintain();
    while (tmp) tmp->maintain(), tmp = tmp->parent;
  }
  return x;
}
int findAssoMax(Treap *root, long long l, long long r) {
  int ret = INT_MIN;
  while (root) {
    root->push();
    if (root->key >= l && root->key <= r)
      break;
    else if (root->key < l)
      root = root->right;
    else
      root = root->left;
  }
  if (root) {
    root->push();
    ret = std::max(ret, root->f);
    Treap *z1 = root->left, *z2 = root->right;
    while (z1) {
      z1->push();
      if (z1->key >= l) {
        ret = std::max(ret, z1->f);
        if (z1->right) {
          z1->right->push();
          ret = std::max(ret, z1->right->maxf);
        }
        z1 = z1->left;
      } else
        z1 = z1->right;
    }
    while (z2) {
      z2->push();
      if (z2->key <= r) {
        ret = std::max(ret, z2->f);
        if (z2->left) {
          z2->left->push();
          ret = std::max(ret, z2->left->maxf);
        }
        z2 = z2->right;
      } else
        z2 = z2->left;
    }
  }
  return ret;
}
const int MAX = 1e5 + 20;
pair<long long, long long> eles[MAX];
long long x[MAX], t[MAX];
int n;
long long v;
int dp[MAX];
template <typename T>
inline void hash_combine(size_t &seed, const T &value) {
  seed ^= hash<T>()(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template <typename T>
inline void hash_val(size_t &seed, const T &val) {
  hash_combine(seed, val);
}
template <typename T, typename... Types>
inline void hash_val(size_t &seed, const T &val, const Types &...args) {
  hash_combine(seed, val);
  hash_val(seed, args...);
}
template <typename... Types>
inline size_t hash_val(const Types &...args) {
  size_t seed = 0;
  hash_val(seed, args...);
  return seed;
}
class obHash {
 public:
  std::size_t operator()(const pair<long long, long long> &c) const {
    return hash_val(c.first, c.second);
  }
};
unordered_map<pair<long long, long long>, int, obHash> ban;
long long gcd(long long a, long long b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%lld%lld", &x[i], &t[i]);
  scanf("%lld", &v);
  for (int i = 1; i <= n; i++) {
    long long d = gcd(x[i], t[i]);
    ban[{t[i] / d, x[i] / d}]++;
  }
  int ans2 = 0;
  for (auto &ele : ban) {
    ans2 = max(ans2, ele.second);
  }
  for (int i = 1; i <= n; i++)
    eles[i].first = x[i] - v * t[i], eles[i].second = v * t[i] + x[i];
  sort(eles + 1, eles + n + 1,
       [](const pair<long long, long long> &a,
          const pair<long long, long long> &b) {
         if (a.first != b.first)
           return a.first < b.first;
         else
           return a.second > b.second;
       });
  Treap *root = 0;
  dp[1] = 1;
  insert(root, eles[1].second, 1);
  for (int i = 2; i <= n; i++) {
    long long curv = eles[i].second;
    int mx = findAssoMax(root, curv, LLONG_MAX);
    if (mx == INT_MIN) {
      dp[i] = 1;
    } else
      dp[i] = mx + 1;
    Treap *ff = access(root, curv);
    if (ff == 0)
      insert(root, curv, dp[i]);
    else {
      ff->push();
      if (ff->f < dp[i]) {
        ff->f = dp[i];
        while (ff) {
          ff->maintain();
          ff = ff->parent;
        }
      }
    }
  }
  int ans = 0;
  for (int i = 1; i <= n; i++) ans = max(ans, dp[i]);
  printf("%d %d\n", ans2, ans);
  return 0;
}
