a0909e4603ad7bef868ac0fd6fac471e39b916ae22038078e428104e494bc308
// https://szkopul.edu.pl/problemset/problem/wOKsnzwNqHqXqiX6m3AkufgX/site/?key=statement
// Bitada
#include <bits/stdc++.h>
// #define GARY_DBG
#define GARY_LIB
constexpr int sizik = 3003;
#define ar std::array
typedef std::vector<std::vector<int>> _kra;
int n, m, k;
std::vector<int> kra1[sizik], kra2[sizik], kra3[sizik];
namespace wzor {
std::pair<int, int> kra_idx[2 * sizik];
int kra_idx_rev[sizik][sizik];
std::vector<int> s[2 * sizik];
int dp[sizik][2 * sizik];
int calc_perms(int u, const std::vector<int>& t1_children, const std::vector<int>& t2_children) {
int d1 = t1_children.size();
int d2 = t2_children.size();
if (d1 > d2) return 0;
if (d1 == 0) return 1;
if (d1 == 1) {
int64_t sum = 0;
int t1_child = t1_children[0];
int edge_idx = kra_idx_rev[t1_child][u];
for (int v2 : t2_children) {
sum = (sum + dp[v2][edge_idx]) % k;
}
return (int)sum;
}
if (d1 == 2) {
int64_t sum = 0;
int t1_c1 = t1_children[0];
int t1_c2 = t1_children[1];
int e1 = kra_idx_rev[t1_c1][u];
int e2 = kra_idx_rev[t1_c2][u];
for (int i = 0; i < d2; ++i) {
for (int j = 0; j < d2; ++j) {
if (i == j) continue;
int64_t term = (1LL * dp[t2_children[i]][e1] * dp[t2_children[j]][e2]) % k;
sum = (sum + term) % k;
}
}
return (int)sum;
}
if (d1 == 3) {
int64_t sum = 0;
int e1 = kra_idx_rev[t1_children[0]][u];
int e2 = kra_idx_rev[t1_children[1]][u];
int e3 = kra_idx_rev[t1_children[2]][u];
const auto& c = t2_children;
auto add_term = [&](int i, int j, int l) {
int64_t term = dp[c[i]][e1];
term = (term * dp[c[j]][e2]) % k;
term = (term * dp[c[l]][e3]) % k;
sum = (sum + term) % k;
};
add_term(0, 1, 2);
add_term(0, 2, 1);
add_term(1, 0, 2);
add_term(1, 2, 0);
add_term(2, 0, 1);
add_term(2, 1, 0);
return (int)sum;
}
return 0;
}
void DFS_parent(int v, int p) {
for (const auto& u : kra2[v]) {
if (u == p) continue;
kra3[v].push_back(u);
DFS_parent(u, v);
}
}
int64_t ans = 0;
int X;
void DFS(int v, int p) {
for (const auto& u : kra3[v]) {
DFS(u, v);
}
for (int i = 1; i <= X; i++) {
const int u = kra_idx[i].first;
dp[v][i] = calc_perms(u, s[i], kra3[v]);
}
}
void solve_wzor() {
int root = 0;
for (int i = 1; i <= m; i++) {
if (kra2[i].size() < 2) {
root = i;
break;
}
}
DFS_parent(root, root);
int idx = 0;
for (int i = 1; i <= n; i++) {
for (const auto& u : kra1[i]) {
kra_idx[++idx] = {i, u};
kra_idx_rev[i][u] = idx;
for (const auto& w : kra1[i]) {
if (w != u) {
s[idx].push_back(w);
}
}
}
}
X = (2 * n - 2);
DFS(root, root);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int64_t val = calc_perms(i, kra1[i], kra3[j]);
ans = (ans + val) % k;
}
}
std::cout << ans << '\n';
}
} // namespace wzor
void solve() {
std::cin >> n >> m >> k;
for (int i = 0; i < n - 1; i++) {
int a, b;
std::cin >> a >> b;
kra1[a].push_back(b);
kra1[b].push_back(a);
}
for (int i = 0; i < m - 1; i++) {
int a, b;
std::cin >> a >> b;
kra2[a].push_back(b);
kra2[b].push_back(a);
}
if (k == 1) {
std::cout << "0\n";
return;
}
if (n == 1) {
std::cout << (m % k) << '\n';
return;
}
if (n == 2) {
std::cout << ((2LL * (m - 1)) % k) << '\n';
return;
}
wzor::solve_wzor();
}
int32_t main() {
#ifndef GARY_DBG
std::ios_base::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
#endif
int t = 1;
// std::cin >> t;
for (; t > 0; t--) {
solve();
}
return 0;
}