#include <bits/stdc++.h>
const int kInf = 0x3f3f3f3f, kMod = 1e9 + 7;
const long long kInf64 = 0x3f3f3f3f3f3f3f3f;
int mod;
template <typename T>
inline void UMin(T& x, const T& y) {
  if (x > y) x = y;
}
template <typename T>
inline void UMax(T& x, const T& y) {
  if (x < y) x = y;
}
inline int Add(int a, int b) { return (a += b) >= mod ? a - mod : a; }
inline int Sub(int a, int b) { return (a -= b) < 0 ? a + mod : a; }
inline int Mul(int a, int b) { return 1ll * a * b % mod; }
int FPow(int bs, int ex = mod - 2) {
  int res = 1;
  for (; ex; bs = Mul(bs, bs), ex >>= 1)
    if (ex & 1) res = Mul(res, bs);
  return res;
}
const int kMaxn = 1005;
const int kPr[] = {2, 3, 5, 7, 9, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
int n, m;
int DP[kMaxn][13], son[13], hash[13], prv[13], sz[13];
std::vector<int> G[kMaxn], T[13];
void Dfs(int, int);
void Gao(int, int);
int main() {
  scanf("%d", &n);
  for (int i = 1, x, y; i < n; ++i) {
    scanf("%d%d", &x, &y);
    G[x].push_back(y), G[y].push_back(x);
  }
  scanf("%d", &m);
  for (int i = 1, x, y; i < m; ++i) {
    scanf("%d%d", &x, &y);
    --x, --y;
    T[x].push_back(y), T[y].push_back(x);
  }
  mod = 1e9 + 7;
  int ans = 0;
  std::set<int> S;
  for (int i = 0; i < m; ++i) {
    std::fill(prv, prv + m, -1);
    std::fill(son, son + m, 0);
    Dfs(i, -1);
    if (S.count(hash[i])) continue;
    S.insert(hash[i]);
    Gao(1, 0);
    for (int u = 1; u <= n; ++u) ans = Add(ans, DP[u][i]);
  }
  printf("%d\n", ans);
  return 0;
}
void Gao(int u, int fa) {
  for (auto v : G[u]) {
    if (v == fa) continue;
    Gao(v, u);
  }
  static int nxt[(1 << 12) + 5], pre[(1 << 12) + 5];
  for (int i = 0; i < m; ++i) {
    for (int s = son[i]; s; s = s - 1 & son[i]) nxt[s] = 0;
    nxt[0] = 1;
    for (auto v : G[u]) {
      if (v == fa) continue;
      for (int s = son[i]; s; s = s - 1 & son[i]) pre[s] = nxt[s];
      pre[0] = nxt[0];
      for (int j = 0; j < m; ++j) {
        if (son[i] >> j & 1 && DP[v][j]) {
          for (int s = son[i]; s; s = s - 1 & son[i]) {
            if (s >> j & 1 && (prv[j] == -1 || s >> prv[j] & 1))
              nxt[s] = Add(nxt[s], Mul(pre[s ^ 1 << j], DP[v][j]));
          }
        }
      }
    }
    DP[u][i] = nxt[son[i]];
  }
}
inline bool CmpHash(int u, int v) { return hash[u] < hash[v]; }
void Dfs(int u, int fa) {
  hash[u] = sz[u] = 1;
  std::vector<int> vec;
  for (auto v : T[u]) {
    if (v == fa) continue;
    Dfs(v, u);
    sz[u] += sz[v];
    vec.push_back(v);
    son[u] |= 1 << v;
  }
  std::sort(vec.begin(), vec.end(), CmpHash);
  int la = -1;
  for (auto v : vec) {
    hash[u] = Add(hash[u], Mul(hash[v], kPr[sz[v] - 1]));
    if (~la && hash[v] == hash[la]) prv[v] = la;
    la = v;
  }
}

### Prompt

Construct a cpp code solution to the problem outlined:

You are given two trees (connected undirected acyclic graphs) S and T.

Count the number of subtrees (connected subgraphs) of S that are isomorphic to tree T. Since this number can get quite large, output it modulo 109 + 7.

Two subtrees of tree S are considered different, if there exists a vertex in S that belongs to exactly one of them.

Tree G is called isomorphic to tree H if there exists a bijection f from the set of vertices of G to the set of vertices of H that has the following property: if there is an edge between vertices A and B in tree G, then there must be an edge between vertices f(A) and f(B) in tree H. And vice versa — if there is an edge between vertices A and B in tree H, there must be an edge between f - 1(A) and f - 1(B) in tree G.

Input

The first line contains a single integer |S| (1 ≤ |S| ≤ 1000) — the number of vertices of tree S.

Next |S| - 1 lines contain two integers ui and vi (1 ≤ ui, vi ≤ |S|) and describe edges of tree S.

The next line contains a single integer |T| (1 ≤ |T| ≤ 12) — the number of vertices of tree T.

Next |T| - 1 lines contain two integers xi and yi (1 ≤ xi, yi ≤ |T|) and describe edges of tree T.

Output

On the first line output a single integer — the answer to the given task modulo 109 + 7.

Examples

Input

5
1 2
2 3
3 4
4 5
3
1 2
2 3


Output

3


Input

3
2 3
3 1
3
1 2
1 3


Output

1


Input

7
1 2
1 3
1 4
1 5
1 6
1 7
4
4 1
4 2
4 3


Output

20


Input

5
1 2
2 3
3 4
4 5
4
4 1
4 2
4 3


Output

0

### Response

```cpp
#include <bits/stdc++.h>
const int kInf = 0x3f3f3f3f, kMod = 1e9 + 7;
const long long kInf64 = 0x3f3f3f3f3f3f3f3f;
int mod;
template <typename T>
inline void UMin(T& x, const T& y) {
  if (x > y) x = y;
}
template <typename T>
inline void UMax(T& x, const T& y) {
  if (x < y) x = y;
}
inline int Add(int a, int b) { return (a += b) >= mod ? a - mod : a; }
inline int Sub(int a, int b) { return (a -= b) < 0 ? a + mod : a; }
inline int Mul(int a, int b) { return 1ll * a * b % mod; }
int FPow(int bs, int ex = mod - 2) {
  int res = 1;
  for (; ex; bs = Mul(bs, bs), ex >>= 1)
    if (ex & 1) res = Mul(res, bs);
  return res;
}
const int kMaxn = 1005;
const int kPr[] = {2, 3, 5, 7, 9, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
int n, m;
int DP[kMaxn][13], son[13], hash[13], prv[13], sz[13];
std::vector<int> G[kMaxn], T[13];
void Dfs(int, int);
void Gao(int, int);
int main() {
  scanf("%d", &n);
  for (int i = 1, x, y; i < n; ++i) {
    scanf("%d%d", &x, &y);
    G[x].push_back(y), G[y].push_back(x);
  }
  scanf("%d", &m);
  for (int i = 1, x, y; i < m; ++i) {
    scanf("%d%d", &x, &y);
    --x, --y;
    T[x].push_back(y), T[y].push_back(x);
  }
  mod = 1e9 + 7;
  int ans = 0;
  std::set<int> S;
  for (int i = 0; i < m; ++i) {
    std::fill(prv, prv + m, -1);
    std::fill(son, son + m, 0);
    Dfs(i, -1);
    if (S.count(hash[i])) continue;
    S.insert(hash[i]);
    Gao(1, 0);
    for (int u = 1; u <= n; ++u) ans = Add(ans, DP[u][i]);
  }
  printf("%d\n", ans);
  return 0;
}
void Gao(int u, int fa) {
  for (auto v : G[u]) {
    if (v == fa) continue;
    Gao(v, u);
  }
  static int nxt[(1 << 12) + 5], pre[(1 << 12) + 5];
  for (int i = 0; i < m; ++i) {
    for (int s = son[i]; s; s = s - 1 & son[i]) nxt[s] = 0;
    nxt[0] = 1;
    for (auto v : G[u]) {
      if (v == fa) continue;
      for (int s = son[i]; s; s = s - 1 & son[i]) pre[s] = nxt[s];
      pre[0] = nxt[0];
      for (int j = 0; j < m; ++j) {
        if (son[i] >> j & 1 && DP[v][j]) {
          for (int s = son[i]; s; s = s - 1 & son[i]) {
            if (s >> j & 1 && (prv[j] == -1 || s >> prv[j] & 1))
              nxt[s] = Add(nxt[s], Mul(pre[s ^ 1 << j], DP[v][j]));
          }
        }
      }
    }
    DP[u][i] = nxt[son[i]];
  }
}
inline bool CmpHash(int u, int v) { return hash[u] < hash[v]; }
void Dfs(int u, int fa) {
  hash[u] = sz[u] = 1;
  std::vector<int> vec;
  for (auto v : T[u]) {
    if (v == fa) continue;
    Dfs(v, u);
    sz[u] += sz[v];
    vec.push_back(v);
    son[u] |= 1 << v;
  }
  std::sort(vec.begin(), vec.end(), CmpHash);
  int la = -1;
  for (auto v : vec) {
    hash[u] = Add(hash[u], Mul(hash[v], kPr[sz[v] - 1]));
    if (~la && hash[v] == hash[la]) prv[v] = la;
    la = v;
  }
}

```