#include <bits/stdc++.h>   using namespace std;   const int Maxn = 1010, Maxm = 20;   const unsigned long long Seed = 19990213;   const long long Mod = 1000000007;   int n, m, cnt, tot1, fst1[Maxn], pre1[Maxn << 1], to1[Maxn << 1], tot2,       fst2[Maxm], pre2[Maxm << 1], to2[Maxm << 1], bel[Maxm], tot[Maxm],       stat[(1 << 12) + 10][Maxm], cur[Maxm], S, w[Maxm], size[Maxm];   bool vis[Maxn], leaf[Maxm];   long long f[Maxn][Maxm], g[Maxn][(1 << 12) + 10], ans;   unsigned long long ha[Maxm];   map<unsigned long long, bool> Hash;   vector<int> son[Maxn], sub[Maxm];   int Get() {     char ch;     int v = 0;     bool f = false;     while (!isdigit(ch = getchar()))       if (ch ==  - ) f = true;     v = ch - 48;     while (isdigit(ch = getchar())) v = v * 10 + ch - 48;     if (f)       return -v;     else       return v;   }   void AddE1(int x, int y) {     pre1[++tot1] = fst1[x], fst1[x] = tot1, to1[tot1] = y;     pre1[++tot1] = fst1[y], fst1[y] = tot1, to1[tot1] = x;   }   void AddE2(int x, int y) {     pre2[++tot2] = fst2[x], fst2[x] = tot2, to2[tot2] = y;     pre2[++tot2] = fst2[y], fst2[y] = tot2, to2[tot2] = x;   }   bool cmp(const int &a, const int &b) {     return ha[a] < ha[b] || (ha[a] == ha[b] && size[a] < size[b]);   }   void Add(long long &x, long long y) {     x += y;     if (x >= Mod) x -= Mod;   }   void Calc(int x, int fa) {     leaf[x] = true, size[x] = 1;     sub[x].clear();     for (int i = fst2[x]; i; i = pre2[i])       if (to2[i] != fa) {         Calc(to2[i], x);         size[x] += size[to2[i]];         sub[x].push_back(to2[i]);         leaf[x] = false;       }     if (leaf[x])       ha[x] = 666072;     else {       ha[x] = 0;       sort(sub[x].begin(), sub[x].end(), cmp);       for (int i = 0; i < sub[x].size(); i++)         ha[x] = (ha[x] * Seed + ha[sub[x][i]]) % Mod;       ha[x] = ha[x] * 1234 % Mod;     }   }   void Transform(int x, int w, int s) {     if (x == cnt + 1) {       S = max(S, s);       for (int i = 1; i <= cnt; i++) stat[s][i] = cur[i];       return;     } else {       for (int i = 0; i <= tot[x]; i++) {         cur[x] = i;         Transform(x + 1, w * (tot[x] + 1), s + i * w);       }     }   }   void dfs(int x) {     vis[x] = true;     son[x].clear();     for (int i = fst1[x]; i; i = pre1[i])       if (!vis[to1[i]]) son[x].push_back(to1[i]), dfs(to1[i]);     int len1 = int(son[x].size());     for (int i = 1; i <= m; i++)       if (leaf[i])         f[x][i] = 1;       else if (len1 > 0) {         f[x][i] = 0, cnt = 0, S = 0;         int len2 = int(sub[i].size());         for (int j = 0; j <= len2 - 1; j++) {           bel[++cnt] = sub[i][j], tot[cnt] = 1;           for (; j < len2 - 1 && ha[sub[i][j]] == ha[sub[i][j + 1]] &&                  size[sub[i][j]] == size[sub[i][j + 1]];                j++)             tot[cnt]++;         }         w[1] = 1;         for (int j = 2; j <= cnt; j++) w[j] = w[j - 1] * (tot[j - 1] + 1);         Transform(1, 1, 0);         for (int s = 0; s <= S; s++) g[0][s] = 0;         g[0][S] = 1;         for (int j = 0; j <= len1 - 1; j++) {           int u = son[x][j];           for (int s = 0; s <= S; s++) g[j + 1][s] = g[j][s];           for (int k = 1; k <= cnt; k++) {             int v = bel[k];             if (f[u][v]) {               for (int s = 0; s <= S; s++)                 if (stat[s][k]) {                   Add(g[j + 1][s - w[k]], g[j][s] * f[u][v] % Mod);                 }             }           }         }         f[x][i] = g[len1][0];       }   }   void solve(int root) {     for (int i = 1; i <= n; i++) vis[i] = false;     dfs(1);     long long res = 0;     for (int i = 1; i <= n; i++) {       Add(ans, f[i][root]);       Add(res, f[i][root]);       for (int j = 1; j <= m; j++) f[i][j] = 0;     }   }   int main() {     n = Get();     int x, y;     for (int i = 1; i <= n - 1; i++) x = Get(), y = Get(), AddE1(x, y);     m = Get();     for (int i = 1; i <= m - 1; i++) x = Get(), y = Get(), AddE2(x, y);     for (int i = 1; i <= m; i++) {       Calc(i, -1);       if (!Hash[ha[i]]) {         Hash[ha[i]] = true;         solve(i);       }     }     cout << ans << endl;     return 0;   }