#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 10, maxm = 1000000 + 10;
int n, m, mod;
struct Edge{
int to, next;
Edge(){}
Edge(int _t, int _n): to(_t), next(_n){}
}e[maxm * 2];
int fir[maxn * 2] = {0}, cnt = 0;
inline void add(int u, int v){
e[++cnt] = Edge(v, fir[u]); fir[u] = cnt;
}
int belong[maxn], siz[maxn * 2] = {0}, bcnt = 0;
int dfn[maxn], low[maxn], index = 0;
int sta[maxn], top = 0;
bool ins[maxn] = {false};
void tarjan(int u){
ins[u] = true;
sta[++top] = u;
dfn[u] = low[u] = ++index;
for(int v, i = fir[u]; i; i = e[i].next){
v = e[i].to;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(ins[v]) low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]){
int now;
bcnt++;
do{
now = sta[top--];
ins[now] = false;
belong[now] = bcnt;
siz[bcnt]++;
}while(now != u);
}
}
int ind[maxn * 2] = {0}, q[maxn], h, t;
void tsort(){
for(int v, u = 1; u <= n; u++)
for(int i = fir[u]; i; i = e[i].next){
v = e[i].to;
if(belong[v] != belong[u]){
ind[belong[v]]++;
add(belong[u], belong[v]);
}
}
h = t = 0;
for(int i = n + 1; i <= bcnt; i++)
if(!ind[i]) q[t++] = i;
int u, v;
while(h != t){
u = q[h++];
for(int i = fir[u]; i; i = e[i].next){
v = e[i].to;
ind[v]--;
if(!ind[v]) q[t++] = v;
}
}
}
int f[maxn * 2], g[maxn * 2];
int mark[maxn * 2] = {0};
void dp(){
int u, v;
for(int i = h; ~i; i--){
u = q[i];
f[u] = siz[u];
g[u] = 1;
for(int j = fir[u]; j; j = e[j].next){
v = e[j].to;
if(mark[v] == u) continue;
mark[v] = u;
if(f[v] + siz[u] > f[u]){
f[u] = f[v] + siz[u];
g[u] = g[v];
}
else if(f[v] + siz[u] == f[u]) g[u] = (g[u] + g[v]) % mod;
}
}
}
int main(){
scanf("%d %d %d", &n, &m, &mod);
for(int u, v, i = 1; i <= m; i++){
scanf("%d %d", &u, &v);
add(u, v);
}
bcnt = n;
for(int i = 1; i <= n; i++)
if(!dfn[i]) tarjan(i);
tsort();
dp();
int ans = 0, sum = 0;
for(int i = n + 1; i <= bcnt; i++){
if(f[i] > ans){
ans = f[i];
sum = g[i];
}
else if(f[i] == ans) sum = (sum + g[i]) % mod;
}
printf("%d\n%d\n", ans, sum);
return 0;
}