/+ dub.sdl:
    name "F"
    dependency "dcomp" version=">=0.7.3"
+/

import std.stdio, std.algorithm, std.range, std.conv;
// import dcomp.foundation, dcomp.scanner;

// import dcomp.modint;
alias Mint = ModInt!(10^^9 + 7);

Mint[] fact, iFac;
static this() {
    fact = factTable!Mint(10000);
    iFac = invFactTable!Mint(10000);
}
Mint C(int n, int k) {
    if (n < 0 || n < k) return Mint(0);
    return fact[n] * iFac[k] * iFac[n-k];
}

int n;
int[] a, b, ap, bp;
int[][] cnt;

// import dcomp.functional;
memoCont!calcBase calc;
Mint calcBase(int x, int y, int k, int up) {
    int d = cnt[x][y] - 2*k;
    if (d < 0) return Mint(0);
    if (k < d) return Mint(0);
//    writeln("debug ", x, " ", y, " ", k, " ", up, " -> ", d);
    //d fix, k-d ?
    if (k == n/3) {
        assert(n-cnt[x][y] == k-d);
        return fact[k-d];
    }
    if (x == n || y == n) return Mint(0);

    if (bp[a[x]] < y) return calc(x+1, y, k, up);
    if (ap[b[y]] < x) return calc(x, y+1, k, up);


    Mint sm = 0;
    if (up) {
        sm += calc(x, y, k, false);
        if (a[x] == b[y]) {
            return Mint(k-d) * calc(x+1, y+1, k, true);
        } else {
            sm += Mint(k-d) * calc(x+1, y, k, true);
        }
    } else {
        if (a[x] != b[y]) {
            sm += calc(x+1, y+1, k+1, true);
            sm += Mint(k-d) * calc(x, y+1, k, false);
        }
    }
    return sm;
}

int main() {
    Scanner sc = new Scanner(stdin);
    sc.read(n, a, b);
    calc.init([[0, n], [0, n], [0, n/3], [0, 1]]);
    a[] -= 1; b[] -= 1;
    ap = new int[n];
    bp = new int[n];
    foreach (i; 0..n) {
        ap[a[i]] = i;
        bp[b[i]] = i;
    }
    cnt = new int[][](n+1, n+1);
    foreach (i; 0..n+1) {
        foreach (j; 0..n+1) {
            auto c = new bool[n];
            foreach (d; a[0..i]) {
                c[d] = true;
            }
            foreach (d; b[0..j]) {
                c[d] = true;
            }
            cnt[i][j] = c.count(true).to!int;
        }
    }

    Mint off = 1;
    foreach (i; 0..n) {
        if (i % 3 == 0) continue;
        off *= Mint(i);
    }
//    writeln(off);
    Mint ans = calc(0, 0, 0, true);
//    writeln(ans);
    writeln(off * ans);
    return 0;
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/modint.d */
// module dcomp.modint;

// import dcomp.numeric.primitive;

 
struct ModInt(uint MD) if (MD < int.max) {
    import std.conv : to;
    uint v;
    this(int v) {this(long(v));}
    this(long v) {this.v = (v%MD+MD)%MD;}
    static auto normS(uint x) {return (x<MD)?x:x-MD;}
    static auto make(uint x) {ModInt m; m.v = x; return m;}
     
    auto opBinary(string op:"+")(ModInt r) const {return make(normS(v+r.v));}
     
    auto opBinary(string op:"-")(ModInt r) const {return make(normS(v+MD-r.v));}
     
    auto opBinary(string op:"*")(ModInt r) const {return make((ulong(v)*r.v%MD).to!uint);}
     
    auto opBinary(string op:"/")(ModInt r) const {return this*inv(r);}
    auto opOpAssign(string op)(ModInt r) {return mixin ("this=this"~op~"r");}
     
    static ModInt inv(ModInt x) {return ModInt(extGcd!int(x.v, MD)[0]);}
    string toString() {return v.to!string;}
}

 
 

 

 
struct DModInt(string name) {
    import std.conv : to;
    static uint MD;
    uint v;
    this(int v) {this(long(v));}
    this(long v) {this.v = ((v%MD+MD)%MD).to!uint;}
    static auto normS(uint x) {return (x<MD)?x:x-MD;}
    static auto make(uint x) {DModInt m; m.MD = MD; m.v = x; return m;}
     
    auto opBinary(string op:"+")(DModInt r) const {return make(normS(v+r.v));}
     
    auto opBinary(string op:"-")(DModInt r) const {return make(normS(v+MD-r.v));}
     
    auto opBinary(string op:"*")(DModInt r) const {return make((ulong(v)*r.v%MD).to!uint);}
     
    auto opBinary(string op:"/")(DModInt r) const {return this*inv(r);}
    auto opOpAssign(string op)(DModInt r) {return mixin ("this=this"~op~"r");}
     
    static DModInt inv(DModInt x) {
        return DModInt(extGcd!int(x.v, MD)[0]);
    }
    string toString() {return v.to!string;}
}

 
 

 

template isModInt(T) {
    const isModInt =
        is(T : ModInt!MD, uint MD) || is(S : DModInt!S, string s);
}


T[] factTable(T)(size_t length) if (isModInt!T) {
    import std.range : take, recurrence;
    import std.array : array;
    return T(1).recurrence!((a, n) => a[n-1]*T(n)).take(length).array;
}

 
T[] invFactTable(T)(size_t length) if (isModInt!T) {
    import std.algorithm : map, reduce;
    import std.range : take, recurrence, iota;
    import std.array : array;
    auto res = new T[length];
    res[$-1] = T(1) / iota(1, length).map!T.reduce!"a*b";
    foreach_reverse (i, v; res[0..$-1]) {
        res[i] = res[i+1] * T(i+1);
    }
    return res;
}

T[] invTable(T)(size_t length) if (isModInt!T) {
    auto f = factTable!T(length);
    auto invf = invFactTable!T(length);
    auto res = new T[length];
    foreach (i; 1..length) {
        res[i] = invf[i] * f[i-1];
    }
    return res;
}

 
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/numeric/primitive.d */
// module dcomp.numeric.primitive;

import std.traits;
import std.bigint;

 
Unqual!T pow(T, U)(T x, U n) if (!isFloatingPoint!T && (isIntegral!U || is(U == BigInt))) {
    return pow(x, n, T(1));
}

 
Unqual!T pow(T, U, V)(T x, U n, V e)
if ((isIntegral!U || is(U == BigInt)) && is(Unqual!T == Unqual!V)) {
    Unqual!T b = x, v = e;
    Unqual!U m = n;
    while (m) {
        if (m & 1) v *= b;
        b *= b;
        m /= 2;
    }
    return v;
}

 

 
T lcm(T)(in T a, in T b) {
    import std.numeric : gcd;
    return a / gcd(a,b) * b;
}

 
 

 
 
T[3] extGcd(T)(in T a, in T b) 
if (!isIntegral!T || isSigned!T)  
{
    if (b==0) {
        return [T(1), T(0), a];
    } else {
        auto e = extGcd(b, a%b);
        return [e[1], e[0]-a/b*e[1], e[2]];
    }
}

 
 
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/functional.d */
// module dcomp.functional;

 
struct memoCont(alias pred) {
    import core.exception : RangeError;
    import std.range, std.algorithm, std.conv;
    import std.string : join;
    import std.traits : ReturnType, ParameterTypeTuple, isIntegral;
    import std.typecons : tuple, Tuple;
    import std.meta;
    alias R = ReturnType!pred;
    alias Args = ParameterTypeTuple!pred;
    static assert (allSatisfy!(isIntegral, Args));
    static immutable N = Args.length;
    int[2][N] rng;
    int[N] len;
    R[] dp;
    bool[] used;
    void init(int[2][N] rng) {
        this.rng = rng;
        len = rng[].map!(a => a[1]-a[0]+1).array;
        int sz = len.reduce!"a*b";
        dp = new R[sz];
        used = new bool[sz];
    }
    R opCall(Args args) {
        int idx, base = 1;
        foreach (i, v; args) {
            version(assert) {
                if (v < rng[i][0] || rng[i][1] < v) {
                    throw new RangeError;
                }
            }
            assert(rng[i][0] <= v && v <= rng[i][1]);
            idx += base*(v - rng[i][0]);
            base *= len[i];
        }
        if (used[idx]) return dp[idx];
        used[idx] = true;
        auto r = pred(args);
        dp[idx] = r;
        return r;
    }
}

 
 
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/scanner.d */
// module dcomp.scanner;

// import dcomp.array;

 
class Scanner {
    import std.stdio : File;
    import std.conv : to;
    import std.range : front, popFront, array, ElementType;
    import std.array : split;
    import std.traits : isSomeChar, isStaticArray, isArray; 
    import std.algorithm : map;
    File f;
    this(File f) {
        this.f = f;
    }
    char[512] lineBuf;
    char[] line;
    private bool succW() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (!line.empty && line.front.isWhite) {
            line.popFront;
        }
        return !line.empty;
    }
    private bool succ() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (true) {
            while (!line.empty && line.front.isWhite) {
                line.popFront;
            }
            if (!line.empty) break;
            line = lineBuf[];
            f.readln(line);
            if (!line.length) return false;
        }
        return true;
    }

    private bool readSingle(T)(ref T x) {
        import std.algorithm : findSplitBefore;
        import std.string : strip;
        import std.conv : parse;
        if (!succ()) return false;
        static if (isArray!T) {
            alias E = ElementType!T;
            static if (isSomeChar!E) {
                 
                 
                auto r = line.findSplitBefore(" ");
                x = r[0].strip.dup;
                line = r[1];
            } else static if (isStaticArray!T) {
                foreach (i; 0..T.length) {
                    bool f = succW();
                    assert(f);
                    x[i] = line.parse!E;
                }
            } else {
                FastAppender!(E[]) buf;
                while (succW()) {
                    buf ~= line.parse!E;
                }
                x = buf.data;
            }
        } else {
            x = line.parse!T;
        }
        return true;
    }
    int read(T, Args...)(ref T x, auto ref Args args) {
        if (!readSingle(x)) return 0;
        static if (args.length == 0) {
            return 1;
        } else {
            return 1 + read(args);
        }
    }
}


 
 

 
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/foundation.d */
// module dcomp.foundation;
 
static if (__VERSION__ <= 2070) {
    /*
    Copied by https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d
    Copyright: Andrei Alexandrescu 2008-.
    License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
    */
    template fold(fun...) if (fun.length >= 1) {
        auto fold(R, S...)(R r, S seed) {
            import std.algorithm : reduce;
            static if (S.length < 2) {
                return reduce!fun(seed, r);
            } else {
                import std.typecons : tuple;
                return reduce!fun(tuple(seed), r);
            }
        }
    }
     
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/array.d */
// module dcomp.array;

 
T[N] fixed(T, size_t N)(T[N] a) {return a;}

 
 

 
struct FastAppender(A, size_t MIN = 4) {
    import std.algorithm : max;
    import std.conv;
    import std.range.primitives : ElementEncodingType;
    import core.stdc.string : memcpy;

    private alias T = ElementEncodingType!A;
    private T* _data;
    private uint len, cap;
     
    @property size_t length() const {return len;}
    bool empty() const { return len == 0; }
     
    void reserve(size_t nlen) {
        import core.memory : GC;
        if (nlen <= cap) return;
        
        void* nx = GC.malloc(nlen * T.sizeof);

        cap = nlen.to!uint;
        if (len) memcpy(nx, _data, len * T.sizeof);
        _data = cast(T*)(nx);
    }
    void free() {
        import core.memory : GC;
        GC.free(_data);
    }
     
    void opOpAssign(string op : "~")(T item) {
        if (len == cap) {
            reserve(max(MIN, cap*2));
        }
        _data[len++] = item;
    }
     
    void insertBack(T item) {
        this ~= item;
    }
     
    void removeBack() {
        len--;
    }
     
    void clear() {
        len = 0;
    }
    ref inout(T) back() inout { assert(len); return _data[len-1]; }
    ref inout(T) opIndex(size_t i) inout { return _data[i]; }
     
    T[] data() {
        return (_data) ? _data[0..len] : null;
    }
}

 
 

/*
This source code generated by dcomp and include dcomp's source code.
dcomp's Copyright: Copyright (c) 2016- Kohei Morita. (https://github.com/yosupo06/dcomp)
dcomp's License: MIT License(https://github.com/yosupo06/dcomp/blob/master/LICENSE.txt)
*/


Measured memory_bytes: 223612