//Lib
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
 
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
//#include<stack>
#include<set>
#include<map>
using namespace std;
//Macro
#define rep(i,a,b)  for(int i=a,tt=b;i<=tt;++i)
#define drep(i,a,b) for(int i=a,tt=b;i>=tt;--i)
#define erep(i,e,x) for(int i=x;i;i=e[i].next)
#define irep(i,x)   for(set<int>::iterator i=x.begin();i!=x.end();i++)
#define read()  (strtol(ipos,&ipos,10))
#define sqr(x)  ((x)*(x))
#define pb  push_back
#define PS  system("pause");
typedef long long   ll;
typedef pair<int,int> pii;
const int oo=~0U>>1;
const double inf=1e100;
const double eps=1e-6;
string name="", in=".in", out=".out";
//Var
struct S
{
    int size,sum;
    S():size(0),sum(1){}
}f[100008],ans;
struct E
{
    int next,node;
}e[1000008];
int n,m,mod,tot;
int stack[100008],dfn[100008],low[100008],top,idx,cnt;
int belong[100008],ind[100008],size[100008],h[100008];
bool vis[100008];
set<int> E[100008];
queue<int> q;
vector<int> vec;
void add(int a,int b){e[++tot].next=h[a];e[tot].node=b;h[a]=tot;}
void Update(S &a,S &b)
{
    if(a.size>b.size)return;
    if(a.size<b.size){a=b;return;}
    a.sum=(a.sum+b.sum)%mod;
}
void DFS(int u)
{
    dfn[u]=low[u]=++idx;
    stack[++top]=u;vis[u]=true;
    int v;
    erep(i,e,h[u])
    {
        if(!dfn[v=e[i].node])
        {
            DFS(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]) low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        ++cnt;
        do
        {
            belong[v=stack[top--]]=cnt;
            vis[v]=false;
        }while(u!=v);
    }
}
void Tarjan()
{
    rep(i,1,n)if(!dfn[i])DFS(i);
    rep(i,1,n)
    {
        int id=belong[i];size[id]++;
        erep(x,e,h[i])if(belong[e[x].node]!=id)E[id].insert(belong[e[x].node]);
    }
}
void Work()
{
    int u,v;
    scanf("%d%d%d",&n,&m,&mod);
    rep(i,1,m)scanf("%d%d",&u,&v),add(u,v);
    Tarjan();
    rep(i,1,cnt)
        irep(it,E[i])
            ind[*it]++;
    rep(i,1,cnt)if(!ind[i])q.push(i);
    while(!q.empty())
    {
        u=q.front();q.pop();vec.pb(u);
        irep(i,E[u])
            if(!(--ind[*i]))
                q.push(*i);
    }
    for(vector<int>::reverse_iterator i=vec.rbegin();i!=vec.rend();i++)
    {
        irep(it,E[*i])
            Update(f[*i],f[*it]);
        f[*i].size=(f[*i].size+size[*i])%mod;
    }
    rep(i,1,cnt)Update(ans,f[i]);
    printf("%d\n%d\n",ans.size,ans.sum);
}
int main()
{
//  freopen((name+in).c_str(),"r",stdin);
//  freopen((name+out).c_str(),"w",stdout);
//  Init();
    Work();
    return 0;
}