#include <iostream>
#include <vector>
using namespace std;
// Używamy typu long long, aby uniknąć przepełnienia przed modulo,
// chociaż przy dodawaniu intów modulo wystarczyłoby int.
// Modulo z treści zadania: 10^9 + 9
const long long MOD = 1000000009;
int main() {
// Optymalizacja wejścia/wyjścia dla C++ (ważne przy krótkim limicie czasu)
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N;
if (!(cin >> N)) return 0;
// Tablica typów dla liczb 1..2N
// 0 = C (dowolny), 1 = A (wiersz 1), 2 = B (wiersz 2)
vector<int> type(2 * N + 1, 0);
int M;
cin >> M;
for (int i = 0; i < M; ++i) {
int val;
cin >> val;
// Zabezpieczenie na wypadek nieprawidłowych danych wejściowych, choć w zadaniach zwykle są poprawne
if (val <= 2 * N) type[val] = 1;
}
int K;
cin >> K;
for (int i = 0; i < K; ++i) {
int val;
cin >> val;
if (val <= 2 * N) type[val] = 2;
}
// dp[r1] = liczba sposobów na ułożenie dotychczasowych liczb,
// mając dokładnie r1 elementów w pierwszym wierszu.
// Rozmiar N+1, bo r1 może być od 0 do N.
vector<long long> dp(N + 1, 0);
// Stan początkowy: 0 liczb wstawionych, 0 w pierwszym wierszu -> 1 sposób.
dp[0] = 1;
// Iterujemy po liczbach od 1 do 2N
for (int k = 1; k <= 2 * N; ++k) {
vector<long long> next_dp(N + 1, 0);
// Iterujemy po możliwych licznościach pierwszego wiersza (r1) z poprzedniego kroku
// Optymalizacja: r1 nie może być większe niż k-1 (wszystkie liczby w R1) i nie większe niż N.
int limit = min(k - 1, N);
for (int r1 = 0; r1 <= limit; ++r1) {
if (dp[r1] == 0) continue;
int r2 = (k - 1) - r1; // Liczba elementów w wierszu 2 przed wstawieniem k
// Opcja 1: Wstaw k do Wiersza 1
// Warunki: k jest w A lub C, oraz mamy miejsce w wierszu 1
if ((type[k] == 1 || type[k] == 0) && r1 + 1 <= N) {
next_dp[r1 + 1] = (next_dp[r1 + 1] + dp[r1]);
if (next_dp[r1 + 1] >= MOD) next_dp[r1 + 1] -= MOD;
}
// Opcja 2: Wstaw k do Wiersza 2
// Warunki: k jest w B lub C, oraz zachowujemy warunek kolumn (r2 + 1 <= r1)
// Uwaga: r2 + 1 to nowa liczba elementów w wierszu 2. Musi być <= AKTUALNEJ liczbie w wierszu 1 (r1).
if ((type[k] == 2 || type[k] == 0) && r2 + 1 <= r1) {
next_dp[r1] = (next_dp[r1] + dp[r1]);
if (next_dp[r1] >= MOD) next_dp[r1] -= MOD;
}
}
// Przejście do nowego stanu
dp = next_dp;
}
// Wynikiem jest liczba sposobów, gdy mamy N elementów w wierszu 1
// (co implikuje N elementów w wierszu 2, bo łącznie 2N)
cout << dp[N] << endl;
return 0;
}