#include <bits/stdc++.h>
using namespace std;
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define int int64_t
int n, k, m, N;
vector<int> t, cnt, longest, v[500005];
void build() {
for (int i = 0; i < N; i++) t[i + N] = cnt[i] + 1;
for (int i = N - 1; i > 0; i--) t[i] = t[i << 1] * t[i << 1 | 1] % m;
}
void update(int p, int val) {
p += N;
t[p] = t[p] + val;
if (t[p] < 0) t[p] += m;
for (p >>= 1; p > 0; p >>= 1) t[p] = t[p << 1] * t[p << 1 | 1] % m;
}
int query(int l, int r) {
int res = 1;
for (l += N, r += N; l < r; l >>= 1, r >>= 1) {
if (l & 1) res = res * t[l++] % m;
if (r & 1) res = res * t[--r] % m;
}
return res;
}
int32_t main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
cin >> n >> k >> m;
for (int i = 0; i < n; i++) {
int x, y; cin >> x >> y;
v[--y].push_back(x);
}
for (int i = 0; i < k; i++) sort(all(v[i]));
sort(v, v + k, [](vector<int>& a, vector<int>& b) {
if (a.empty()) return false;
if (b.empty()) return true;
return a.back() > b.back();
});
for (int i = k - 1; i >= 0; i--) {
if (v[i].empty()) longest.push_back(0);
else longest.push_back(v[i].back());
}
cnt.assign(k, 0);
for (int i = 0; i < k; i++) cnt[i] = sz(v[i]);
N = k;
t.assign(2 * N, 1);
build();
priority_queue<pair<int,int>> pq;
for (int i = 0; i < k; i++) {
for (int x : v[i]) {
pq.emplace(x, i);
}
}
vector<vector<int>> dp(k, vector<int>(2, 0));
for (int i = 0; i < k; i++) {
if (v[i].empty()) continue;
int mx = v[i].back();
while (!pq.empty() && pq.top().first > mx / 2) {
auto top = pq.top(); pq.pop();
int ttype = top.second;
cnt[ttype]--;
update(ttype, -1);
}
int c = upper_bound(all(v[i]), mx / 2) - v[i].begin();
dp[i][0] = 1;
dp[i][1] = c;
dp[i][0] = dp[i][0] * query(i + 1, k) % m;
dp[i][1] = dp[i][1] * query(i + 1, k) % m;
if (c < sz(v[i])) {
int idx = lower_bound(all(longest), 2 * v[i][c]) - longest.begin();
int L = k - idx, R = i - 1;
if (L <= R) {
dp[i][0] = dp[i][0] * query(L, R + 1) % m;
}
}
}
int ans = 0;
for (int i = 0; i < k; i++) ans = (ans + dp[i][0] + dp[i][1]) % m;
cout << ans << '\n';
return 0;
}