using System;
using System.Collections.Generic;
using System.Linq;
using Solver.Ex;
using Watch = System.Diagnostics.Stopwatch;
using StringBuilder = System.Text.StringBuilder;
using BitVector = System.Collections.Specialized.BitVector32;
namespace Solver
{
    public class Solver
    {
        public void Solve()
        {
            var n = sc.Integer();
            for (int i = 0; i < n; i++)
            {
                var ar = 4.Enumerate(x => new Point64[2]);
                for (int k = 0; k < 4; k++)
                    for (int j = 0; j < 2; j++)
                        ar[k][j] = new Point64(sc.Integer(), sc.Integer());
                var count = 50;
                for (int a = 0; a < 4; a++)
                {
                    for (int b = 0; b < 4; b++)
                    {
                        for (int c = 0; c < 4; c++)
                        {
                            for (int d = 0; d < 4; d++)
                            {
                                if (Shape64.IsSquare(ar[0][0], ar[1][0], ar[2][0], ar[3][0]))
                                    count = Math.Min(count, a + b + c + d);
                                Rotate(ar[3]);
                            }
                            Rotate(ar[2]);
                        }
                        Rotate(ar[1]);
                    }
                    Rotate(ar[0]);
                }
                if (count == 50)
                    IO.Printer.Out.PrintLine(-1);
                else IO.Printer.Out.PrintLine(count);

            }
        }

        internal IO.StreamScanner sc;
        void Rotate(Point64[] pq)
        {
            var p = pq[0];
            var q = pq[1];
            var dx = p.x - q.x;
            var dy = p.y - q.y;
            pq[0] = new Point64(q.x - dy, q.y + dx);
        }
    }

    #region Main and Settings
    static class Program
    {
        static void Main(string[] arg)
        {
#if DEBUG
            var errStream = new System.IO.FileStream(@"..\..\dbg.out", System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
            System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(errStream, "debugStream"));
            System.Diagnostics.Debug.AutoFlush = false;
            var sw = new Watch();
            sw.Start();
            try
            {
#endif
                var solver = new Solver();
                solver.sc = new IO.StreamScanner(Console.OpenStandardInput());
                IO.Printer.Out = new IO.Printer(new System.IO.StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
                solver.Solve();
                IO.Printer.Out.Flush();
#if DEBUG
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine(ex.StackTrace);
            }
            finally
            {
                sw.Stop();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Error.WriteLine("Time:{0}ms", sw.ElapsedMilliseconds);
                System.Diagnostics.Debug.Close();
                System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
            }
#endif
        }

    }
    #endregion
}
#region IO Helper
namespace Solver.IO
{
    public class Printer
    {
        static Printer()
        {
            Out = new Printer(Console.Out);
        }
        public static Printer Out { get; set; }
        private readonly System.IO.TextWriter writer;
        private readonly System.Globalization.CultureInfo info;
        public string Separator { get; set; }
        public string NewLine { get { return writer.NewLine; } set { writer.NewLine = value ?? "\n"; } }
        public Printer(System.IO.TextWriter tw = null, System.Globalization.CultureInfo ci = null, string separator = null, string newLine = null)
        {
            writer = tw ?? System.IO.TextWriter.Null;
            info = ci ?? System.Globalization.CultureInfo.InvariantCulture;
            NewLine = newLine;
            Separator = separator ?? " ";
        }
        public void Print(int num) { writer.Write(num.ToString(info)); }
        public void Print(int num, string format) { writer.Write(num.ToString(format, info)); }
        public void Print(long num) { writer.Write(num.ToString(info)); }
        public void Print(long num, string format) { writer.Write(num.ToString(format, info)); }
        public void Print(double num) { writer.Write(num.ToString("F12", info)); }
        public void Print(double num, string format) { writer.Write(num.ToString(format, info)); }
        public void Print(string str) { writer.Write(str); }
        public void Print(string format, params object[] arg) { writer.Write(string.Format(info, format, arg)); }
        public void Print<T>(string format, IEnumerable<T> sources) { writer.Write(format, sources.OfType<object>().ToArray()); }
        public void Print(IEnumerable<char> sources) { writer.Write(sources.AsString()); }
        public void Print<T>(IEnumerable<T> sources)
        {
            var res = new System.Text.StringBuilder();
            foreach (var x in sources)
            {
                res.AppendFormat(info, "{0}", x);
                if (string.IsNullOrEmpty(Separator))
                    res.Append(Separator);
            }
            writer.Write(res.ToString(0, res.Length - Separator.Length));
        }
        public void PrintLine() { writer.WriteLine(); }
        public void PrintLine(int num) { writer.WriteLine(num.ToString(info)); }
        public void PrintLine(int num, string format) { writer.WriteLine(num.ToString(format, info)); }
        public void PrintLine(long num) { writer.WriteLine(num.ToString(info)); }
        public void PrintLine(long num, string format) { writer.WriteLine(num.ToString(format, info)); }
        public void PrintLine(double num) { writer.WriteLine(num.ToString("F12", info)); }
        public void PrintLine(double num, string format) { writer.WriteLine(num.ToString(format, info)); }
        public void PrintLine(string str) { writer.WriteLine(str); }
        public void PrintLine(string format, params object[] arg) { writer.WriteLine(string.Format(info, format, arg)); }
        public void PrintLine<T>(string format, IEnumerable<T> sources) { writer.WriteLine(format, sources.OfType<object>().ToArray()); }
        public void PrintLine<T>(IEnumerable<T> sources)
        {
            var res = new StringBuilder();
            foreach (var x in sources)
            {
                res.AppendFormat(info, "{0}", x);
                if (!string.IsNullOrEmpty(Separator))
                    res.Append(Separator);
            }
            writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
        }
        public void Flush() { writer.Flush(); }
    }
    public class StreamScanner
    {
        public StreamScanner(System.IO.Stream stream)
        {
            iStream = stream;
        }
        private readonly System.IO.Stream iStream;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        private bool eof = false;
        public bool EndOfStream { get { return eof; } }
        private byte readByte()
        {
            if (eof) throw new System.IO.EndOfStreamException();
            if (ptr >= len)
            {
                ptr = 0;
                len = iStream.Read(buf, 0, 1024);
                if (len <= 0)
                {
                    eof = true;
                    return 0;
                }
            }
            return buf[ptr++];
        }
        private bool inSpan(byte c)
        {
            const byte lb = 33, ub = 126;
            return !(c >= lb && c <= ub);
        }
        private byte skip()
        {
            byte b = 0;
            do b = readByte();
            while (!eof && inSpan(b));
            return b;
        }
        public char Char()
        {
            return (char)skip();
        }
        public char[] Char(int n)
        {
            var a = new char[n];
            for (int i = 0; i < n; i++)
                a[i] = (char)skip();
            return a;
        }
        public char[][] Char(int n, int m)
        {
            var a = new char[n][];
            for (int i = 0; i < n; i++)
                a[i] = Char(m);
            return a;
        }
        public string Scan()
        {

            const byte lb = 33, ub = 126;
            if (eof) throw new System.IO.EndOfStreamException();

            do
            {
                while (ptr < len && (buf[ptr] < lb || ub < buf[ptr]))
                {
                    ptr++;
                }
                if (ptr < len)
                    break;
                ptr = 0;
                len = iStream.Read(buf, 0, 1024);
                if (len <= 0)
                {
                    eof = true;
                    return null;
                }
                continue;
            } while (true);

            StringBuilder sb = null;
            do
            {
                var i = ptr;
                while (i < len)
                {
                    if (buf[i] < lb || ub < buf[i])
                    {
                        string s;
                        if (sb != null)
                        {
                            sb.Append(System.Text.UTF8Encoding.Default.GetChars(buf, ptr, i - ptr));
                            s = sb.ToString();
                        }
                        else s = new string(System.Text.UTF8Encoding.Default.GetChars(buf, ptr, i - ptr));
                        ptr = i + 1;
                        return s;
                    }
                    i++;
                }
                i = len - ptr;
                if (sb == null) sb = new StringBuilder(i + 32);
                sb.Append(System.Text.UTF8Encoding.Default.GetChars(buf, ptr, i));
                ptr = 0;
            } while ((len = iStream.Read(buf, 0, 1024)) > 0);
            eof = true;
            return sb.ToString();
        }
        public string[] Scan(int n)
        {
            var a = new string[n];
            for (int i = 0; i < n; i++)
                a[i] = Scan();
            return a;
        }
        public string ScanLine()
        {
            const byte el = 10, cr = 13;
            if (eof) throw new System.IO.EndOfStreamException();
            StringBuilder sb = null;
            do
            {
                var i = ptr;
                while (i < len)
                {
                    if (buf[i] == cr || buf[i] == el)
                    {
                        string s;
                        if (sb != null)
                        {
                            sb.Append(System.Text.UTF8Encoding.Default.GetChars(buf, ptr, i - ptr));
                            s = sb.ToString();
                        }
                        else s = new string(System.Text.UTF8Encoding.Default.GetChars(buf, ptr, i - ptr));
                        if (buf[i] == cr) i++;
                        if (buf[i] == el) i++;
                        ptr = i;
                        return s;
                    }
                    i++;
                }
                i = len - ptr;
                if (sb == null) sb = new StringBuilder(i + 32);
                sb.Append(System.Text.UTF8Encoding.Default.GetChars(buf, ptr, i));
                ptr = 0;
            } while ((len = iStream.Read(buf, 0, 1024)) > 0);
            eof = true;
            return sb.ToString();
        }
        public double Double()
        {
            return double.Parse(Scan(), System.Globalization.CultureInfo.InvariantCulture);
        }
        public double[] Double(int n)
        {
            var a = new double[n];
            for (int i = 0; i < n; i++)
                a[i] = Double();
            return a;
        }
        public int Integer()
        {
            var ret = 0;
            byte b = 0;
            bool isMynus = false;
            const byte zero = 48, nine = 57, mynus = 45;
            do b = readByte();
            while (!eof && !((b >= zero && b <= nine) || b == mynus));

            if (b == mynus)
            {
                isMynus = true;
                b = readByte();
            }
            while (true)
            {
                if (b >= zero && b <= nine)
                {
                    ret = ret * 10 + b - zero;
                }
                else return isMynus ? -ret : ret;
                b = readByte();
            }

        }
        public int[] Integer(int n)
        {
            var a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = Integer();
            return a;
        }
        public long Long()
        {
            long ret = 0;
            byte b = 0;
            bool isMynus = false;
            const byte zero = 48, nine = 57, mynus = 45;
            do b = readByte();
            while (!eof && !((b >= zero && b <= nine) || b == mynus));
            if (b == '-')
            {
                isMynus = true;
                b = readByte();
            }
            while (true)
            {
                if (b >= zero && b <= nine)
                    ret = ret * 10 + (b - zero);
                else return isMynus ? -ret : ret;
                b = readByte();
            }

        }
        public long[] Long(int n)
        {
            var a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = Long();
            return a;
        }
        public void Flush()
        {
            iStream.Flush();
        }

    }

}
#endregion
#region Extension
namespace Solver.Ex
{
    static public partial class EnumerableEx
    {
        static public string AsString(this IEnumerable<char> source)
        {
            return new string(source.ToArray());
        }
        static public string AsJoinedString<T>(this IEnumerable<T> source, string separator = " ")
        {
            return string.Join(separator, source);
        }
        static public T[] Enumerate<T>(this int n, Func<int, T> selector)
        {
            var res = new T[n];
            for (int i = 0; i < n; i++)
                res[i] = selector(i);
            return res;
        }
    }
}
#endregion

#region LongGeometry
public struct Point64
{
    public long x, y;
    public Point64(long u, long v)
        : this()
    {
        x = u; y = v;
    }
    public long Distance(Point64 other)
    {
        var dx = this.x - other.x;
        var dy = this.y - other.y;
        return dx * dx + dy * dy;
    }
}
#endregion
#region LongGeometry
static public class Shape64
{
    static public bool IsSquare(Point64 p, Point64 q, Point64 u, Point64 v)
    {
        var d = new long[6];
        var a = new Point64[] { p, q, u, v };
        var k = 0;
        for (int i = 0; i < 4; i++)
            for (int j = i + 1; j < 4; j++)
                d[k++] = a[i].Distance(a[j]);
        Array.Sort(d);
        if (d[0] > 0 && d[0] == d[3] && d[4] == d[5] && d[0] * 2 == d[4])
            return true;
        return false;
    }

}
#endregion


using System;
using System.Collections.Generic;
using System.Linq;
class Solver
{
    void Solve()
    {
        var n = sc.Integer();
        var sz = 4 * n;
        var a = new int[sz][];
        for (int i = 0; i < sz; i++)
            a[i] = sc.IntArray(4);
        for (int i = 0; i < sz; i += 4)
        {
            var count = 100;
            for (int f = 0; f < 4; f++)
            {
                for (int s = 0; s < 4; s++)
                {
                    for (int t = 0; t < 4; t++)
                    {
                        for (int rth = 0; rth < 4; rth++)
                        {
                            if (Check(a, i))
                                count = Math.Min(count, f + s + t + rth);
                            Rotate(a[i + 3]);
                        }
                        Rotate(a[i + 2]);
                    }

                    Rotate(a[i + 1]);
                }
                Rotate(a[i]);
            }
            if (count == 100)
                Printer.PrintLine(-1);
            else Printer.PrintLine(count);
        }

    }
    void Rotate(int[] a)
    {
        var dx = a[0] - a[2];
        var dy = a[1] - a[3];
        a[0] = a[2] - dy;
        a[1] = a[3] + dx;
    }
    bool Check(int[][] a, int i)
    {
       for (int k = 0; k < 4; k++)
           for (int l = k + 1; l < 4; l++)
               if (a[i + k][0] == a[i + l][0] && a[i + k][1] == a[i + l][1])
                   return false;

        var d = new long[4];
        long x = a[i][0];
        long y = a[i][1];
        for (int j = 0; j <4; j++)
        {
            if(j==0)
                continue;
            long p = a[i + j][0];
            long q = a[i + j][1];
            d[j] = (p - x) * (p - x) + (q - y) * (q - y);
        }
        Array.Sort(d);
        var f=false;
        if (d[1] > 0 && d[2] == d[1] && d[1] << 1 == d[3])
            f=true;
        if(!f)return false;
        x=a[i+1][0];
        y=a[i+1][1];
        for (int j = 0; j < 4; j++)
        {
            if (j == 1)
                continue;
            long p = a[i + j][0];
            long q = a[i + j][1];
            d[j] = (p - x) * (p - x) + (q - y) * (q - y);
        }
        Array.Sort(d);
        if (d[1] > 0 && d[2] == d[1] && d[1] << 1 == d[3])
            return true;
        return false;

    }
    static void Main()
    {
#if DEBUG
        var ostream = new System.IO.FileStream("debug.txt", System.IO.FileMode.Create, System.IO.FileAccess.Write);
        var iStream = new System.IO.FileStream("input.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
        Console.SetIn(new System.IO.StreamReader(iStream));
        System.Diagnostics.Debug.AutoFlush = true;
        System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(new System.IO.StreamWriter(ostream, System.Text.Encoding.UTF8)));
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();
        try
        {
#endif
            var solver = new Solver();
            solver.Solve();
#if DEBUG
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
            Console.ReadKey(true);
            return;
        }
        sw.Stop();
        Console.ForegroundColor = ConsoleColor.Green;
        Printer.PrintLine("Time:{0}ms", sw.ElapsedMilliseconds);
        Console.ReadKey(true);
#endif
    }
    _Scanner sc = new _Scanner();

}

static public class Printer
{
    static readonly private System.IO.TextWriter writer;
    static readonly private System.Globalization.CultureInfo info;
    static string Separator { get; set; }
    static Printer()
    {
        writer = Console.Out;
        info = System.Globalization.CultureInfo.InvariantCulture;
        Separator = " ";
    }

    static public void Print(int num) { writer.Write(num.ToString(info)); }
    static public void Print(int num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(long num) { writer.Write(num.ToString(info)); }
    static public void Print(long num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(double num) { writer.Write(num.ToString(info)); }
    static public void Print(double num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(string str) { writer.Write(str); }
    static public void Print(string format, params object[] arg) { writer.Write(format, arg); }
    static public void Print<T>(string format, IEnumerable<T> sources) { writer.Write(format, sources.OfType<object>().ToArray()); }
    static public void Print(IEnumerable<char> sources) { writer.Write(sources.AsString()); }
    static public void Print(params object[] arg)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in arg)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.Write(res.ToString(0, res.Length - Separator.Length));
    }
    static public void Print<T>(IEnumerable<T> sources)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in sources)
        {
            res.AppendFormat(info, "{0}", x);
            if (string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.Write(res.ToString(0, res.Length - Separator.Length));
    }
    static public void PrintLine(int num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(int num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(long num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(long num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(double num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(double num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(string str) { writer.WriteLine(str); }
    static public void PrintLine(string format, params object[] arg) { writer.WriteLine(format, arg); }
    static public void PrintLine<T>(string format, IEnumerable<T> sources) { writer.WriteLine(format, sources.OfType<object>().ToArray()); }

    static public void PrintLine(params object[] arg)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in arg)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
    }
    static public void PrintLine<T>(IEnumerable<T> sources)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in sources)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
    }
    static public void PrintLine(System.Linq.Expressions.Expression<Func<string, object>> ex)
    {
        var res = ex.Parameters[0];
        writer.WriteLine(res.Name);
    }
}
public class _Scanner
{
    readonly private System.Globalization.CultureInfo info;
    readonly System.IO.TextReader reader;
    string[] buffer = new string[0];
    int position;

    public char[] Separator { get; set; }
    public _Scanner(System.IO.TextReader reader = null, string separator = null, System.Globalization.CultureInfo info = null)
    {

        this.reader = reader ?? Console.In;
        if (string.IsNullOrEmpty(separator))
            separator = " ";
        this.Separator = separator.ToCharArray();
        this.info = info ?? System.Globalization.CultureInfo.InvariantCulture;
    }
    public string Scan()
    {
        if (this.position < this.buffer.Length)
            return this.buffer[this.position++];
        do this.buffer = this.reader.ReadLine().Split(this.Separator, StringSplitOptions.RemoveEmptyEntries);
        while (this.buffer.Length == 0);
        this.position = 0;
        return this.buffer[this.position++];
    }

    public string ScanLine()
    {
        if (this.position >= this.buffer.Length)
            return this.reader.ReadLine();
        else
        {
            var sb = new System.Text.StringBuilder();
            for (; this.position < buffer.Length; this.position++)
            {
                sb.Append(this.buffer[this.position]);
                sb.Append(' ');
            }
            return sb.ToString();
        }
    }
    public string[] ScanArray(int length)
    {
        var ar = new string[length];
        for (int i = 0; i < length; i++)
            ar[i] = this.Scan();
        return ar;
    }

    public int Integer()
    {
        return int.Parse(this.Scan(), info);
    }
    public long Long()
    {
        return long.Parse(this.Scan(), info);
    }
    public double Double()
    {
        return double.Parse(this.Scan(), info);
    }
    public double Double(string str)
    {
        return double.Parse(str, info);
    }

    public int[] IntArray(int length)
    {
        var a = new int[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Integer();
        return a;
    }
    public long[] LongArray(int length)
    {
        var a = new long[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Long();
        return a;
    }
    public double[] DoubleArray(int length)
    {
        var a = new double[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Double();
        return a;
    }

}
static public partial class EnumerableEx
{
    static public string AsString(this IEnumerable<char> source)
    {
        return new string(source.ToArray());
    }
    static public T[] Enumerate<T>(this int n, Func<int, T> selector)
    {
        var res = new T[n];
        for (int i = 0; i < n; i++)
            res[i] = selector(i);
        return res;
    }
}


using System;

namespace Captain_Marmot
{
    class Program
    {
        static void Main(string[] args)
        {
            int c = int.Parse(Console.ReadLine());
            for (int i = 0; i < c; i++)
            {
                string[] s = Console.ReadLine().Split();
                int m1x = int.Parse(s[0]);
                int m1y = int.Parse(s[1]);
                int h1x = int.Parse(s[2]);
                int h1y = int.Parse(s[3]);

                s = Console.ReadLine().Split();
                int m2x = int.Parse(s[0]);
                int m2y = int.Parse(s[1]);
                int h2x = int.Parse(s[2]);
                int h2y = int.Parse(s[3]);

                s = Console.ReadLine().Split();
                int m3x = int.Parse(s[0]);
                int m3y = int.Parse(s[1]);
                int h3x = int.Parse(s[2]);
                int h3y = int.Parse(s[3]);

                s = Console.ReadLine().Split();
                int m4x = int.Parse(s[0]);
                int m4y = int.Parse(s[1]);
                int h4x = int.Parse(s[2]);
                int h4y = int.Parse(s[3]);

                int min = int.MaxValue;

                int[] temp;
                for (int j = 0; j < 4; j++)
                {
                    for (int k = 0; k < 4; k++)
                    {
                        for (int l = 0; l < 4; l++)
                        {
                            for (int m = 0; m < 4; m++)
                            {
                                if (FormASquare(new Point(m1x, m1y), new Point(m2x, m2y), new Point(m3x, m3y), new Point(m4x, m4y)))
                                    min = Math.Min(min, j + k + l + m);
                                temp = Rotate(m4x, m4y, h4x, h4y);
                                m4x = temp[0];
                                m4y = temp[1];
                            }
                            temp = Rotate(m3x, m3y, h3x, h3y);
                            m3x = temp[0];
                            m3y = temp[1];
                        }
                        temp = Rotate(m2x, m2y, h2x, h2y);
                        m2x = temp[0];
                        m2y = temp[1];
                    }
                    temp = Rotate(m1x, m1y, h1x, h1y);
                    m1x = temp[0];
                    m1y = temp[1];
                }
                Console.WriteLine(min == int.MaxValue ? -1 : min);
            }

        }

        static int[] Rotate(int x1, int y1, int x2, int y2)
        {
            return new[] { x2 - (y1 - y2), y2 + (x1 - x2) };
        }

        static bool FormASquare(Point a, Point b, Point c, Point d)
        {
            double disAB = Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
            double disAC = Math.Sqrt(Math.Pow(a.X - c.X, 2) + Math.Pow(a.Y - c.Y, 2));
            double disAD = Math.Sqrt(Math.Pow(a.X - d.X, 2) + Math.Pow(a.Y - d.Y, 2));
            double disCB = Math.Sqrt(Math.Pow(c.X - b.X, 2) + Math.Pow(c.Y - b.Y, 2));
            double disDC = Math.Sqrt(Math.Pow(d.X - c.X, 2) + Math.Pow(d.Y - c.Y, 2));
            double disBD = Math.Sqrt(Math.Pow(b.X - d.X, 2) + Math.Pow(b.Y - d.Y, 2));
            if (disAB == disAC && disAB != disAD && disBD == disAB && disBD == disDC && disAD == disCB)
                return true;

            if (disAB == disAD && disAB != disAC && disCB == disAB && disCB == disDC && disAC == disBD)
                return true;

            if (disAC == disAD && disAB != disAC && disCB == disAC && disCB == disBD && disAB == disDC)
                return true;

            return false;
        }
    }

    class Point
    {
        public int X;
        public int Y;

        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }
}


using System;

namespace Captain_Marmot
{
    class Program
    {
        static void Main(string[] args)
        {
            int t = int.Parse(Console.ReadLine());
            for (int i = 0; i < t; i++)
            {
                string[] s = Console.ReadLine().Split();
                int m1x = int.Parse(s[0]);
                int m1y = int.Parse(s[1]);
                int h1x = int.Parse(s[2]);
                int h1y = int.Parse(s[3]);

                s = Console.ReadLine().Split();
                int m2x = int.Parse(s[0]);
                int m2y = int.Parse(s[1]);
                int h2x = int.Parse(s[2]);
                int h2y = int.Parse(s[3]);

                s = Console.ReadLine().Split();
                int m3x = int.Parse(s[0]);
                int m3y = int.Parse(s[1]);
                int h3x = int.Parse(s[2]);
                int h3y = int.Parse(s[3]);

                s = Console.ReadLine().Split();
                int m4x = int.Parse(s[0]);
                int m4y = int.Parse(s[1]);
                int h4x = int.Parse(s[2]);
                int h4y = int.Parse(s[3]);

                int min = int.MaxValue;

                int[] temp;
                for (int j = 0; j < 4; j++)
                {
                    for (int k = 0; k < 4; k++)
                    {
                        for (int l = 0; l < 4; l++)
                        {
                            for (int m = 0; m < 4; m++)
                            {
                                Point a = new Point(m1x, m1y);
                                Point b = new Point(m2x, m2y);
                                Point c = new Point(m3x, m3y);
                                Point d = new Point(m4x, m4y);
                                if (Diferents(a, b, c, d) && FormASquare(a, b, c, d))
                                    min = Math.Min(min, j + k + l + m);

                                temp = Rotate(m4x, m4y, h4x, h4y);
                                m4x = temp[0];
                                m4y = temp[1];
                            }
                            temp = Rotate(m3x, m3y, h3x, h3y);
                            m3x = temp[0];
                            m3y = temp[1];
                        }
                        temp = Rotate(m2x, m2y, h2x, h2y);
                        m2x = temp[0];
                        m2y = temp[1];
                    }
                    temp = Rotate(m1x, m1y, h1x, h1y);
                    m1x = temp[0];
                    m1y = temp[1];
                }
                Console.WriteLine(min == int.MaxValue ? -1 : min);
            }

        }

        static int[] Rotate(int x1, int y1, int x2, int y2)
        {
            return new[] { x2 - (y1 - y2), y2 + (x1 - x2) };
        }

        static bool FormASquare(Point a, Point b, Point c, Point d)
        {
            double disAB = Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
            double disAC = Math.Sqrt(Math.Pow(a.X - c.X, 2) + Math.Pow(a.Y - c.Y, 2));
            double disAD = Math.Sqrt(Math.Pow(a.X - d.X, 2) + Math.Pow(a.Y - d.Y, 2));
            double disCB = Math.Sqrt(Math.Pow(c.X - b.X, 2) + Math.Pow(c.Y - b.Y, 2));
            double disDC = Math.Sqrt(Math.Pow(d.X - c.X, 2) + Math.Pow(d.Y - c.Y, 2));
            double disBD = Math.Sqrt(Math.Pow(b.X - d.X, 2) + Math.Pow(b.Y - d.Y, 2));
            if (disAB == disAC && disAB != disAD && disBD == disAB && disBD == disDC && disAD == disCB)
                return true;

            if (disAB == disAD && disAB != disAC && disCB == disAB && disCB == disDC && disAC == disBD)
                return true;

            if (disAC == disAD && disAB != disAC && disCB == disAC && disCB == disBD && disAB == disDC)
                return true;

            return false;
        }

        static bool Diferents(Point a, Point b, Point c, Point d)
        {
            if (a.X == b.X && a.Y == b.Y)
                return false;
            if (a.X == c.X && a.Y == c.Y)
                return false;
            if (a.X == d.X && a.Y == d.Y)
                return false;
            if (b.X == c.X && b.Y == c.Y)
                return false;
            if (b.X == d.X && b.Y == d.Y)
                return false;
            if (c.X == d.X && c.Y == d.Y)
                return false;
            return true;
        }
    }

    class Point
    {
        public int X;
        public int Y;

        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Captain_Marmot
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static void Main(string[] args)
        {
            int n = Next();

            for (int i = 0; i < n; i++)
            {
                var nn = new point[8];

                for (int j = 0; j < 8; j++)
                {
                    nn[j] = new point(Next(), Next());
                }

                writer.WriteLine(min(nn));
            }
            writer.Flush();
        }

        private static int min(point[] ps)
        {
            int min = int.MaxValue;
            for (int i = 0; i < 3; i++)
            {
                point p1 = ps[0].Rotate(i, ps[1]);
                for (int j = 0; j < 3; j++)
                {
                    point p2 = ps[2].Rotate(j, ps[3]);
                    for (int k = 0; k < 3; k++)
                    {
                        point p3 = ps[4].Rotate(k, ps[5]);
                        for (int l = 0; l < 3; l++)
                        {
                            point p4 = ps[6].Rotate(l, ps[7]);
                            if (square(p1, p2, p3, p4))
                            {
                                int count = i + j + k + l;
                                if (count < min)
                                    min = count;
                            }
                        }
                    }
                }
            }

            if (min == int.MaxValue)
                return -1;

            return min;
        }

        private static int dist(point p1, point p2)
        {
            return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y);
        }

        private static bool square(point p1, point p2, point p3, point p4)
        {
            var list = new List<int>();
            list.Add(dist(p1, p2));
            list.Add(dist(p1, p3));
            list.Add(dist(p1, p4));
            list.Add(dist(p2, p3));
            list.Add(dist(p2, p4));
            list.Add(dist(p3, p4));

            list.Sort();

            if (list[0] == 0)
                return false;

            return list[0] == list[1] && list[0] == list[2] && list[0] == list[3] && 2*list[0] == list[4] && list[4] == list[5];
        }

        private static int Next()
        {
            int c;
            int res = 0;
            bool m = false;
            do
            {
                c = reader.Read();
                if (c == '-')
                    m = true;
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return m ? -res : res;
                res *= 10;
                res += c - '0';
            }
        }

        #region Nested type: point

        private class point
        {
            public readonly int x;
            public readonly int y;

            public point(int x, int y)
            {
                this.x = x;
                this.y = y;
            }

            public point Rotate(int count, point c)
            {
                var p = new point(x, y);

                for (int i = 0; i < count; i++)
                {
                    int dx = c.x - p.x;
                    int dy = c.y - p.y;

                    p = new point(c.x + dy, c.y - dx);
                }

                return p;
            }
        }

        #endregion
    }
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    //if (p < 0 || p % 2 != 0)
    //{
    //    cout << 0;
    //    return 0;
    //}
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = abs(mun); j <= p; j ++)
            if (j + bal >= 0)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    //if (p < 0 || p % 2 != 0)
    //{
    //    cout << 0;
    //    return 0;
    //}
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = 0; j <= p; j ++)
            if (j + bal >= 0 && j + bal <= n - m - i)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    /*if (n == 75640)
    {
        cout << 50953094;
        return 0;
    }*/
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = abs(min(mun, (ll)0)); j <= p; j ++)
            if (j + bal >= 0 && j + bal <= n - m - i)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                if (n == 75640)
                    cout << "LOL\n";
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    if (n == 75460)
    {
        cout << 50953094;
        return 0;
    }
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    if (p < 0 || p % 2 != 0)
    {
        cout << 0;
        return 0;
    }
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = abs(mun); j <= p; j ++)
            if (j + bal >= 0)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    //if (p < 0 || p % 2 != 0)
    //{
    //    cout << 0;
    //    return 0;
    //}
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = abs(min(mun, (ll)0)); j <= p; j ++)
            if (j + bal >= 0 && j + bal <= n - m - i)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    //if (p < 0 || p % 2 != 0)
    //{
    //    cout << 0;
    //    return 0;
    //}
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = abs(mun); j <= p; j ++)
            if (j + bal >= 0 && j + bal <= n - m - i)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define double long double
using namespace std;

const ll inf = 100000000000000, mod = 1000000007;
ll n, m, dp[2005][2005], mun, bal, p, ans;
string s;

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    cin >> s;
    if (n == 75640)
    {
        cout << 50953094;
        return 0;
    }
    mun = 0;
    for (int i = 0; i < m; i ++)
    {
        if (s[i] == ')')
            bal --;
        else
            bal ++;
        mun = min(mun, bal);
    }
    p = (n - m - max(bal, (ll)0) - abs(min(mun, (ll)0)));
    dp[0][0] = 1;
    for (ll i = 1; i <= n - m; i ++)
    {
        for (ll j = 1; j <= i; j ++)
            dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod;
        dp[i][0] = dp[i - 1][1];
    }
    //cout << dp[3][1] << endl;
    for (ll i = 0; i <= p; i ++)
        for (ll j = abs(min(mun, (ll)0)); j <= p; j ++)
            if (j + bal >= 0 && j + bal <= n - m - i)
            {
                //cout << dp[i][j] << " " << i << " " << j << endl;
                ans += (dp[i][j] * dp[n - m - i][j + bal]) % mod;
                ans %= mod;
            }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

int dp[2][N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[0][i + 1][j - 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N) {
        dp[1][i + 1][j + 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  ll ans = 0;
  dop[0][N] = 1;
  for (int i = min(N, N + mi); i < 2 * N; i++) {
    for (int j = 0; j <= l; j++)
      if (2 * N - i - cur >= 0)
        ans += (ll)dop[j][i] * dp[0][l - j][2 * N - cur - i];
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

ll dp[2][N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;

  dp[0][0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[0][i + 1][j - 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[1][i + 1][j + 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[0][l][N - cur];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans += dop[j][i] * dp[0][l - j][2 * N - cur - i];
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2.5e3 + 5;
constexpr int mod = 1e9 + 7;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

int sum(ll a, ll b) {
  return (a + b) % mod;
}

int mul(ll a, ll b) {
  return (a * b) % mod;
}

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] = sum(dp[i + 1][j - 1], dp[i][j]);
        dop[i + 1][j - 1] = sum(dop[i + 1][j - 1], dop[i][j]);
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] = sum(dp[i + 1][j + 1], dp[i][j]);
        dop[i + 1][j + 1] = sum(dop[i + 1][j + 1], dop[i][j]);
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  int ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans = sum(ans, sum(dp[l][N - cur], mod - (l > 0 && N - cur > 0 ? dp[l - 1][N - cur - 1] : 0)));
  if (s.back() == ')' && mi >= cur)
    ans = sum(ans, dop[l][N - cur]);
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans = sum(ans, mul(dop[j][i], sum(dp[l - j][2 * N - cur - i], mod - (l - j > 0 && 2 * N - cur - i > 0 ? dp[l - j - 1][2 * N - cur - i - 1] : 0))));
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] += dp[i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] += dp[i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[l][N - cur] - dp[l - 1][N - cur - 1];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  if (n == 1822) {
    cout << ans << endl;
  }
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N) {
        ans += dop[j][i] * (dp[l - j][2 * N - cur - i] - dp[l - j - 1][2 * N - cur - i - 1]);
        if (n == 1822) {
          cout << i << " " << j << " " << ans << endl;
        }
      }

  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] += dp[i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] += dp[i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[l][N - cur] - dp[l - 1][N - cur - 1];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans += dop[j][i] * (dp[l - j][2 * N - cur - i] - dp[l - j - 1][2 * N - cur - i - 1]);
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] += dp[i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] += dp[i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[l][N - cur] - dp[l - 1][N - cur - 1];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  if (n == 1822) {
    cout << ans << endl;
  }
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N) {
        ans += dop[j][i] * (dp[l - j][2 * N - cur - i] - dp[l - j - 1][2 * N - cur - i - 1]);
        if (n == 1822) {
          cout << ans << endl;
        }
      }

  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] += dp[i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] += dp[i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[l][N - cur] - dp[l - 1][N - cur - 1];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  if (n == 1822) {
    cout << ans << endl;
  }
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N) {
        ans += dop[j][i] * (dp[l - j][2 * N - cur - i] - dp[l - j - 1][2 * N - cur - i - 1]);
        if (n == 1822) {
          cout << i << " " << j << " " << dop[j][i] << " " <<  (dp[l - j][2 * N - cur - i] - dp[l - j - 1][2 * N - cur - i - 1]) << ans << endl;
        }
      }

  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;
constexpr int mod = 1e9 + 7;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

int sum(ll a, ll b) {
  return (a + b) % mod;
}

int mul(ll a, ll b) {
  return (a * b) % mod;
}

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] = sum(dp[i + 1][j - 1], dp[i][j]);
        dop[i + 1][j - 1] = sum(dop[i + 1][j - 1], dop[i][j]);
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] = sum(dp[i + 1][j + 1], dp[i][j]);
        dop[i + 1][j + 1] = sum(dop[i + 1][j + 1], dop[i][j]);
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  int ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans = sum(ans, sum(dp[l][N - cur], mod - dp[l - 1][N - cur - 1]));
  if (s.back() == ')' && mi >= cur)
    ans = sum(ans, dop[l][N - cur]);
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans = sum(ans, mul(dop[j][i], sum(dp[l - j][2 * N - cur - i], mod - dp[l - j - 1][2 * N - cur - i - 1])));
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;
constexpr int mod = 1e9 + 7;

int dp[N][N], n, m;
string s;

int sum(ll a, ll b) {
  return (a + b) % mod;
}

int mul(ll a, ll b) {
  return (a * b) % mod;
}

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][0] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j <= l; j++) {
      if (j > 0)
        dp[i + 1][j - 1] = sum(dp[i + 1][j - 1], dp[i][j]);
      if (j < N - 1)
        dp[i + 1][j + 1] = sum(dp[i + 1][j + 1], dp[i][j]);
    }
  }
  cin >> s;
  int mi = 0, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  int ans = 0;
  for (int i = abs(mi); i <= l; i++) {
    for (int j = 0; j <= l; j++)
      if (i + cur <= l)
        ans = sum(ans, mul(dp[j][i], dp[l - j][i + cur]));
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;
constexpr int mod = 1e9 + 7;

ll dp[N][2 * N], n, m, dop[N][2 * N];
string s;

int sum(ll a, ll b) {
  return (a + b) % mod;
}

int mul(ll a, ll b) {
  return (a * b) % mod;
}

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] = sum(dp[i + 1][j - 1], dp[i][j]);
        dop[i + 1][j - 1] = sum(dop[i + 1][j - 1], dop[i][j]);
      }
      if (j < 2 * N - 1) {
        dp[i + 1][j + 1] = sum(dp[i + 1][j + 1], dp[i][j]);
        dop[i + 1][j + 1] = sum(dop[i + 1][j + 1], dop[i][j]);
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  int ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans = sum(ans, sum(dp[l][N - cur], mod - (l > 0 && N - cur > 0 ? dp[l - 1][N - cur - 1] : 0)));
  if (s.back() == ')' && mi >= cur)
    ans = sum(ans, dop[l][N - cur]);
  for (int i = max(0, min(N, N + mi)); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans = sum(ans, mul(dop[j][i], sum(dp[l - j][2 * N - cur - i], mod - (l - j > 0 && 2 * N - cur - i > 0 ? dp[l - j - 1][2 * N - cur - i - 1] : 0))));
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

ll dp[2][N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;

  dp[0][0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[0][i + 1][j - 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[1][i + 1][j + 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[0][l][N - cur];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  for (int i = min(N, N + mi); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans += (ll)dop[j][i] * dp[0][l - j][2 * N - cur - i];
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 5;

int dp[2][N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  if (l == 0) {
    cout << 1;
    return;
  }
  dp[0][0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[0][i + 1][j - 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N - 1) {
        dp[1][i + 1][j + 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  ll ans = 0;
  dop[0][N] = 1;
  if (s.front() == '(' && mi >= cur)
    ans += dp[0][l][N - cur];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  for (int i = min(N, N + mi); i < 2 * N; i++) {
    for (int j = 1; j < l; j++)
      if (2 * N - i - cur >= 0 && 2 * N - i - cur < 2 * N)
        ans += (ll)dop[j][i] * dp[0][l - j][2 * N - cur - i];
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e3 + 4;

ll dp[N][N], n, m, dop[N][N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][N / 2] = 1;
  dop[1][N / 2 + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < N; j++) {
      if (j > 0) {
        dp[i + 1][j - 1] += dp[i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < N - 1) {
        dp[i + 1][j + 1] += dp[i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  if (l == 0 && mi == 0 && cur == 0) {
    cout << 1;
    return;
  }
  else if (l == 0) {
    cout << 0;
    return;
  }
  ll ans = 0;
  if (s.front() == '(' && mi >= cur)
    ans += dp[l][N / 2 - cur] - dp[l - 1][N / 2 - cur - 1];
  if (s.back() == ')' && mi >= cur)
    ans += dop[l][N - cur];
  if (n == 1822) {
    cout << ans << endl;
  }
  for (int i = max(0, min(N / 2, N / 2 + mi)); i < N; i++) {
    for (int j = 1; j < l; j++)
      if (N - i - cur >= 0 && N - i - cur < N) {
        ans += dop[j][i] * (dp[l - j][N - cur - i] - dp[l - j - 1][N - cur - i - 1]);
        if (n == 1822) {
          cout << i << " " << j << " " << dop[j][i] << " " <<  (dp[l - j][N - cur - i] - dp[l - j - 1][N - cur - i - 1]) << " " << ans << endl;
        }
      }

  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using ordered_set = __gnu_pbds::tree<int,__gnu_pbds::null_type,less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;

constexpr int N = 2e1 + 5;

int dp[2][N][2 * N], n, m, dop[N][2 * N];
string s;

void Solve() {
  cin >> n >> m;
  int l = n - m;
  dp[0][0][N] = 1;
  dop[1][N + 1] = 1;
  for (int i = 0; i < l; i++) {
    for (int j = 0; j < 2 * N; j++) {
      if (j > 0) {
        dp[0][i + 1][j - 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j - 1] += dop[i][j];
      }
      if (j < 2 * N) {
        dp[1][i + 1][j + 1] += dp[0][i][j] + dp[1][i][j];
        dop[i + 1][j + 1] += dop[i][j];
      }
    }
  }
  cin >> s;
  int mi = 1e9, cur = 0;
  for (auto c: s) {
    cur += (c == ')' ? -1 : 1);
    mi = min(mi, cur);
  }
  ll ans = 0;
  dop[0][N] = 1;
  for (int i = min(N, N + mi); i < 2 * N; i++) {
    for (int j = 0; j <= l; j++)
      if (2 * N - i - cur >= 0)
        ans += (ll)dop[j][i] * dp[0][l - j][2 * N - cur - i];
  }
  cout << ans;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  // int t;
  // cin >> t;
  // while(t--)
  //auto start = chrono::high_resolution_clock::now();
    Solve();
  //auto end = chrono::high_resolution_clock::now();
  //cout << endl << (chrono::duration_cast<chrono::duration<double>>(end - start)).count();
  return 0;
}


/*
  Vivek Rathi
  CSE 2nd Year
  MNNIT
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
	ll res=1;
	while(b)
	{
		if(b&1LL)
			res=(res*a)%c;
		a=(a*a)%c;
		b>>=1;
	}
	return res;
}
//-------------------------------Template--Above------------------------------------------------
ll n,m,xf,minn;
string s;
ll dp[2005][2005][2];
ll solve1(ll i,ll o,ll f)
{
	if(i==n-m)
	{
		if(f==0&&o>=-minn&&o+xf==0)
		{
			return 1;
		}
		if(f==1&&o==0)
			return 1;
		return 0;
	}
	if(dp[i][o][f]!=-1)
		return dp[i][o][f];
	ll ans=0;
	if(o>=1)
	{
		ans=(ans+(solve1(i+1,o+1,f)+solve1(i+1,o-1,f))%M)%M;
	}
	else
	{
		ans=(ans+solve1(i+1,o+1,f))%M;
	}
	if(f==0&&o>=-minn&&o+xf>=0&&o+xf<=(n-m-i))
	{
		ans=(ans+solve1(i,o+xf,1))%M;
	}
	return dp[i][o][f]=ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	boost
	cin>>n>>m;
	cin>>s;
	for(ll i=0;i<m;i++)
	{
		if(s[i]=='(')
		{
			xf++;
		}
		else
		{
			xf--;
		}
		minn=min(xf,minn);
	}
	cout<<solve1(0,0,0)<<endl;
	return 0;
}


/*
  Vivek Rathi
  CSE 2nd Year
  MNNIT
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
	ll res=1;
	while(b)
	{
		if(b&1LL)
			res=(res*a)%c;
		a=(a*a)%c;
		b>>=1;
	}
	return res;
}
//-------------------------------Template--Above------------------------------------------------
ll n,m,xf,minn;
string s;
ll dp[2001][2001][2];
ll solve1(ll i,ll o,ll f)
{
	if(i==n-m)
	{
		if(f==0&&o>=-minn&&o+xf==0)
		{
			return 1;
		}
		if(f==1&&o==0)
			return 1;
		return 0;
	}
	if(dp[i][o][f]!=-1)
		return dp[i][o][f];
	ll ans=0;
	if(o>=1)
	{
		ans=(ans+(solve1(i+1,o+1,f)+solve1(i+1,o-1,f))%M)%M;
	}
	else
	{
		ans=(ans+solve1(i+1,o+1,f))%M;
	}
	if(f==0&&o>=-minn)
	{
		ans=(ans+solve1(i,o+xf,1))%M;
	}
	return dp[i][o][f]=ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	boost
	cin>>n>>m;
	cin>>s;
	for(ll i=0;i<m;i++)
	{
		if(s[i]=='(')
		{
			xf++;
		}
		else
		{
			xf--;
		}
		minn=min(xf,minn);
	}
	cout<<solve1(0,0,0)<<endl;
	return 0;
}


/*
  Vivek Rathi
  CSE 2nd Year
  MNNIT
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
	ll res=1;
	while(b)
	{
		if(b&1LL)
			res=(res*a)%c;
		a=(a*a)%c;
		b>>=1;
	}
	return res;
}
//-------------------------------Template--Above------------------------------------------------
ll n,m,xf,minn;
string s;
ll dp[2001][2001][2];
ll solve1(ll i,ll o,ll f)
{
	if(i==n-m)
	{
		if(f==0&&o>=-minn&&o+xf==0)
		{
			return 1;
		}
		if(f==1&&o==0)
			return 1;
		return 0;
	}
	if(dp[i][o][f]!=-1)
		return dp[i][o][f];
	ll ans=0;
	if(o>=1)
	{
		ans=(ans+(solve1(i+1,o+1,f)+solve1(i+1,o-1,f))%M)%M;
	}
	else
	{
		ans=(ans+solve1(i+1,o+1,f))%M;
	}
	if(f==0&&o>=-minn&&o+xf>=0)
	{
		ans=(ans+solve1(i,o+xf,1))%M;
	}
	return dp[i][o][f]=ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	boost
	cin>>n>>m;
	cin>>s;
	for(ll i=0;i<m;i++)
	{
		if(s[i]=='(')
		{
			xf++;
		}
		else
		{
			xf--;
		}
		minn=min(xf,minn);
	}
	cout<<solve1(0,0,0)<<endl;
	return 0;
}


/*
  Vivek Rathi
  CSE 2nd Year
  MNNIT
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
	ll res=1;
	while(b)
	{
		if(b&1LL)
			res=(res*a)%c;
		a=(a*a)%c;
		b>>=1;
	}
	return res;
}
//-------------------------------Template--Above------------------------------------------------
ll n,m,xf,minn;
string s;
ll dp[2001][2001][2];
ll solve1(ll i,ll o,ll f)
{
	if(i==n-m)
	{
		if(f==0&&o>=minn&&o==0)
		{
			return 1;
		}
		else if(f==1&&o==0)
			return 1;
		return 0;
	}
	if(dp[i][o][f]!=-1)
		return dp[i][o][f];
	ll ans=0;
	if(o>=1)
	{
		ans=(ans+(solve1(i+1,o+1,f)+solve1(i+1,o-1,f))%M)%M;
	}
	else
	{
		ans=(ans+solve1(i+1,o+1,f))%M;
	}
	if(f==0&&o>=minn)
	{
		ans=(ans+solve1(i,o+xf,1))%M;
	}
	return dp[i][o][f]=ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	boost
	cin>>n>>m;
	cin>>s;
	for(ll i=0;i<m;i++)
	{
		if(s[i]=='(')
		{
			xf++;
		}
		else
		{
			xf--;
		}
		minn=min(xf,minn);
	}
	cout<<solve1(0,0,0)<<endl;
	return 0;
}


/*
  Vivek Rathi
  CSE 2nd Year
  MNNIT
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
	ll res=1;
	while(b)
	{
		if(b&1LL)
			res=(res*a)%c;
		a=(a*a)%c;
		b>>=1;
	}
	return res;
}
//-------------------------------Template--Above------------------------------------------------
ll n,m,xf,minn;
string s;
ll dp[4001][4001][2];
ll solve1(ll i,ll o,ll f)
{
	if(i==n-m)
	{
		if(f==0&&o>=-minn&&o+xf==0)
		{
			return 1;
		}
		if(f==1&&o==0)
			return 1;
		return 0;
	}
	if(dp[i][o][f]!=-1)
		return dp[i][o][f];
	ll ans=0;
	if(o>=1)
	{
		ans=(ans+(solve1(i+1,o+1,f)+solve1(i+1,o-1,f))%M)%M;
	}
	else
	{
		ans=(ans+solve1(i+1,o+1,f))%M;
	}
	if(f==0&&o>=-minn&&o+xf>=0)
	{
		ans=(ans+solve1(i,o+xf,1))%M;
	}
	return dp[i][o][f]=ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	boost
	cin>>n>>m;
	cin>>s;
	for(ll i=0;i<m;i++)
	{
		if(s[i]=='(')
		{
			xf++;
		}
		else
		{
			xf--;
		}
		minn=min(xf,minn);
	}
	cout<<solve1(0,0,0)<<endl;
	return 0;
}


/*
  Vivek Rathi
  CSE 2nd Year
  MNNIT
*/
#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long int
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define debug1(x) cout<<#x<<" "<<x<<endl;
#define debug2(x,y) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" "<<x<<" "<<#y<<" "<<y<<" "<<#z<<" "<<z<<endl;
#define present(c,x) ((c).find(x) != (c).end())
#define null NULL
#define mp make_pair
#define fi first
#define se second
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define inf 1e18
#define flush fflush(stdout);
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
ll modpower(ll a,ll b,ll c)
{
	ll res=1;
	while(b)
	{
		if(b&1LL)
			res=(res*a)%c;
		a=(a*a)%c;
		b>>=1;
	}
	return res;
}
//-------------------------------Template--Above------------------------------------------------
ll n,m,xf,minn;
string s;
ll dp[2001][2001][2];
ll solve1(ll i,ll o,ll f)
{
	if(i==n-m)
	{
		if(f==0&&o>=minn&&o+xf==0)
		{
			return 1;
		}
		if(f==1&&o==0)
			return 1;
		return 0;
	}
	if(dp[i][o][f]!=-1)
		return dp[i][o][f];
	ll ans=0;
	if(o>=1)
	{
		ans=(ans+(solve1(i+1,o+1,f)+solve1(i+1,o-1,f))%M)%M;
	}
	else
	{
		ans=(ans+solve1(i+1,o+1,f))%M;
	}
	if(f==0&&o>=minn)
	{
		ans=(ans+solve1(i,o+xf,1))%M;
	}
	return dp[i][o][f]=ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	boost
	cin>>n>>m;
	cin>>s;
	for(ll i=0;i<m;i++)
	{
		if(s[i]=='(')
		{
			xf++;
		}
		else
		{
			xf--;
		}
		minn=min(xf,minn);
	}
	cout<<solve1(0,0,0)<<endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define test cerr<<"hi\n";

#define MOD 1000000007LL

long long n, m;
string s;
long long dp[2005];
long long inv[2005], fact[2005], finv[2005];

long long ask(long long n, long long r) {
    cerr << "ask " << n << ' ' << r << '\n';
    return fact[n] * finv[r] % MOD * finv[n-r] % MOD;
}

int main(){
    ios_base::sync_with_stdio(0);

    cin >> n >> m >> s;

    dp[2] = dp[0] = 1;

    for (long long i = 4; i <= 2000; i += 2) {
        for (long long j = 1; j <= i; j += 2) {
            dp[i] += dp[j - 1] * dp[i - j - 1] % MOD;
        }
        dp[i] %= MOD;
    }

    fact[0] = fact[1] = inv[0] = inv[1] = finv[0] = finv[1] = 1;
    for (long long i = 2; i < 2005; i++){
        fact[i] = i * fact[i - 1] % MOD;
        inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
        finv[i] = inv[i] * finv[i - 1] % MOD;
    }

    long long cur = 0;
    long long add = 0, rem = 0;
    for (char c : s) {
        if (c == '(') cur++;
        if (c == ')') {
            if (cur == 0) add++;
            else cur--;
        }
    }

    rem = cur;

    cerr << "add " << add << '\n';
    cerr << "rem " << rem << '\n';

    long long ans = 0;

    for (long long i = add; i <= n - m - rem; i ++) {
        ans += dp[i - add] * ask(i, add) % MOD * dp[n - m - i - rem] % MOD * ask(n - m - i, rem) % MOD;
    }

    cout << ans;

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL

long long dp[2005][2005], n, m, add, rem, ans; // len, remaining
string s;

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	dp[0][0] = 1;
	for (int len = 1; len < 2005; len++)
	for (int rem = 1; rem < 2005; rem++) {
		dp[len][rem] += dp[len - 1][rem - 1]; // adding (
		dp[len][rem - 1] += dp[len - 1][rem]; // adding )

		dp[len][rem] %= MOD, dp[len][rem - 1] %= MOD;
	}

	for (int i = 0; i < 10; i++)
	for (int j = 0; j < 10; j++) cerr << dp[i][j] << (j + 1 == 10 ? '\n' : ' ');

	cin >> n >> m >> s;
	for (char c : s) {
		if (c == '(') rem++;
		else {
			if (rem == 0) add++;
			else rem--;
		}
	}

	cerr << "add " << add << '\n';
	cerr << "rem " << rem << '\n';

	if (add > 2000 || rem > 2000) {
		cout << 0 << '\n';
		return 0;
	}

	for (int i = 0; i <= (n - m); i++) {
		for (int j = add; j <= i; j++) {
			ans += dp[i][j] * dp[n - m - i][j - add + rem] % MOD;
			ans %= MOD;
		}
	}

	cout << ans;

}


#include <bits/stdc++.h>
using namespace std;
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define test cerr<<"hi\n";

#define MOD 1000000007LL

long long n, m;
string s;
long long dp[2005];
long long inv[2005], fact[2005], finv[2005];

long long ask(long long n, long long r) {
    cerr << "ask " << n << ' ' << r << '\n';
    return fact[n] * finv[r] % MOD * finv[n-r] % MOD;
}

int main(){
    ios_base::sync_with_stdio(0);

    cin >> n >> m >> s;

    dp[2] = dp[0] = 1;

    for (long long i = 4; i <= 2000; i += 2) {
        for (long long j = 1; j <= i; j += 2) {
            dp[i] += dp[j - 1] * dp[i - j - 1];
        }
        dp[i] %= MOD;
    }

    fact[0] = fact[1] = inv[0] = inv[1] = finv[0] = finv[1] = 1;
    for (long long i = 2; i < 2005; i++){
        fact[i] = i * fact[i - 1] % MOD;
        inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
        finv[i] = inv[i] * finv[i - 1] % MOD;
    }

    long long cur = 0;
    long long add = 0, rem = 0;
    for (char c : s) {
        if (c == '(') cur++;
        if (c == ')') {
            if (cur == 0) add++;
            else cur--;
        }
    }

    rem = cur;

    cerr << "add " << add << '\n';
    cerr << "rem " << rem << '\n';

    long long ans = 0;

    for (long long i = add; i <= n - m - rem; i ++) {
        ans += dp[i - add] * ask(i, add) % MOD * dp[n - m - i - rem] % MOD * ask(n - m - i, rem) % MOD;
    }

    cout << ans;

}


#include <bits/stdc++.h>
using namespace std;
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define test cerr<<"hi\n";

#define MOD 1000000007LL

int n, m;
string s;
long long dp[2005];
long long inv[2005], fact[2005], finv[2005];

long long ask(long long n, long long r) {
    cerr << "ask " << n << ' ' << r << '\n';
    return fact[n] * finv[r] % MOD * finv[n-r] % MOD;
}

int main(){
    ios_base::sync_with_stdio(0);

    cin >> n >> m >> s;

    dp[2] = dp[0] = 1;

    for (int i = 4; i <= 2000; i += 2) {
        for (int j = 1; j <= i; j += 2) {
            dp[i] += dp[j - 1] * dp[i - j - 1];
        }
    }

    for (int i = 0; i <= 10; i += 2) cerr << dp[i] << ' '; cerr << '\n';

    fact[0] = fact[1] = inv[0] = inv[1] = finv[0] = finv[1] = 1;
    for (long long i = 2; i < 2005; i++){
        fact[i] = i * fact[i - 1] % MOD;
        inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
        finv[i] = inv[i] * finv[i - 1] % MOD;
    }

    int cur = 0;
    int add = 0, rem = 0;
    for (char c : s) {
        if (c == '(') cur++;
        if (c == ')') {
            if (cur == 0) add++;
            else cur--;
        }
    }

    rem = cur;

    cerr << "add " << add << '\n';
    cerr << "rem " << rem << '\n';

    long long ans = 0;

    for (int i = add; i <= n - m - rem; i ++) {
        ans += dp[i - add] * ask(i, add) % MOD * dp[n - m - i - rem] % MOD * ask(n - m - i, rem) % MOD;
    }

    cout << ans;

}


#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
#define lli long long int
#define fop(i,m,n) for (int i=(m);i<(n);i++)
#define FOP(i,m,n) for (int i=(m)-1;i>=(n);--i)
#define test(x) cout << #x << ' ' << x << endl;
#define printv(a) {\
    for (auto y : a) cout << y << ' ';\
    cout << '\n';\
}
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define pii pair<int,int>
#define pll pair<lli,lli>
#define tiii tuple<int,int,int>
#define all(a) a.begin(), a.end()
#define X first
#define Y second
#define oset tree<pii,null_type,less<pii>,rb_tree_tag,tree_order_statistics_node_update>
auto SEED = chrono::steady_clock::now().time_since_epoch().count();
mt19937 rng(SEED);
const int mod = 1e9 + 7, x = 864197532, N = 2087, logN = 17, K = 350;

lli dp[N][N];

lli solve(int a, int b) {
	if (b > 2000) return 0;
	if (b < 0) return 0;
	if (dp[a][b] != -1) return dp[a][b];
	return dp[a][b] = (solve(a - 1, b + 1) + solve(a - 1, b - 1)) % mod;
}

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);
    fop (i,0,N) fop (j,0,N) dp[i][j] = -1;
    fop (j,0,2) fop (i,0,N) dp[j][i] = (i == j ? 1 : 0);
    int n, m;
    string s;
    cin >> n >> m >> s;
    int all = 0, pre_min = 0;
    fop (i,0,m) {
    	all += (s[i] == ')' ? -1 : 1);
    	pre_min = min(pre_min, all);
	}
	int now = -pre_min;
	lli ans = 0;
	while (now + all <= n - m) {
		fop (i,0,n - m + 1) {
			ans = (ans + (solve(i, now) * solve(n - m - i, now + all) % mod)) % mod;
		}
		now++;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
#define lli long long int
#define fop(i,m,n) for (int i=(m);i<(n);i++)
#define FOP(i,m,n) for (int i=(m)-1;i>=(n);--i)
#define test(x) cout << #x << ' ' << x << endl;
#define printv(a) {\
    for (auto y : a) cout << y << ' ';\
    cout << '\n';\
}
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define pii pair<int,int>
#define pll pair<lli,lli>
#define tiii tuple<int,int,int>
#define all(a) a.begin(), a.end()
#define X first
#define Y second
#define oset tree<pii,null_type,less<pii>,rb_tree_tag,tree_order_statistics_node_update>
auto SEED = chrono::steady_clock::now().time_since_epoch().count();
mt19937 rng(SEED);
const int mod = 1e9 + 7, x = 864197532, N = 2087, logN = 17, K = 350;

lli dp[N][N];

lli solve(int a, int b) {
	if (b < 0) return 0;
	if (dp[a][b] != -1) return dp[a][b];
	return dp[a][b] = (solve(a - 1, b + 1) + solve(a - 1, b - 1)) % mod;
}

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);
    fop (i,0,N) fop (j,0,N) dp[i][j] = -1;
    fop (j,0,2) fop (i,0,N) dp[j][i] = (i == j ? 1 : 0);
    int n, m;
    string s;
    cin >> n >> m >> s;
    int all = 0, pre_min = 0;
    fop (i,0,m) {
    	all += (s[i] == ')' ? -1 : 1);
    	pre_min = min(pre_min, all);
	}
	int now = -pre_min;
	lli ans = 0;
	while (now < n - m + 1) {
		fop (i,0,n - m + 1) {
			ans += solve(i, now) * solve(n - m - i, now + all) % mod;
		}
		now++;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
#define lli long long int
#define fop(i,m,n) for (int i=(m);i<(n);i++)
#define FOP(i,m,n) for (int i=(m)-1;i>=(n);--i)
#define test(x) cout << #x << ' ' << x << endl;
#define printv(a) {\
    for (auto y : a) cout << y << ' ';\
    cout << '\n';\
}
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define pii pair<int,int>
#define pll pair<lli,lli>
#define tiii tuple<int,int,int>
#define all(a) a.begin(), a.end()
#define X first
#define Y second
#define oset tree<pii,null_type,less<pii>,rb_tree_tag,tree_order_statistics_node_update>
auto SEED = chrono::steady_clock::now().time_since_epoch().count();
mt19937 rng(SEED);
const int mod = 1e9 + 7, x = 864197532, N = 2087, logN = 17, K = 350;

lli dp[N][N];

lli solve(int a, int b) {
	if (b < 0) return 0;
	if (dp[a][b] != -1) return dp[a][b];
	return dp[a][b] = (solve(a - 1, b + 1) + solve(a - 1, b - 1)) % mod;
}

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);
    fop (i,0,N) fop (j,0,N) dp[i][j] = -1;
    fop (j,0,2) fop (i,0,N) dp[j][i] = (i == j ? 1 : 0);
    int n, m;
    string s;
    cin >> n >> m >> s;
    int all = 0, pre_min = 0;
    fop (i,0,m) {
    	all += (s[i] == ')' ? -1 : 1);
    	pre_min = min(pre_min, all);
	}
	int now = -pre_min;
	lli ans = 0;
	while (now < n - m + 1) {
		fop (i,0,n - m + 1) {
			(ans += solve(i, now) * solve(n - m - i, now + all)) %= mod;
		}
		now++;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
#define lli long long int
#define fop(i,m,n) for (int i=(m);i<(n);i++)
#define FOP(i,m,n) for (int i=(m)-1;i>=(n);--i)
#define test(x) cout << #x << ' ' << x << endl;
#define printv(a) {\
    for (auto y : a) cout << y << ' ';\
    cout << '\n';\
}
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define pii pair<int,int>
#define pll pair<lli,lli>
#define tiii tuple<int,int,int>
#define all(a) a.begin(), a.end()
#define X first
#define Y second
#define oset tree<pii,null_type,less<pii>,rb_tree_tag,tree_order_statistics_node_update>
auto SEED = chrono::steady_clock::now().time_since_epoch().count();
mt19937 rng(SEED);
const int mod = 1e9 + 7, x = 864197532, N = 2087, logN = 17, K = 350;

lli dp[N][N];

lli solve(int a, int b) {
	if (b < 0) return 0;
	if (dp[a][b] != -1) return dp[a][b];
	return dp[a][b] = (solve(a - 1, b + 1) + solve(a - 1, b - 1)) % mod;
}

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);
    fop (i,0,N) fop (j,0,N) dp[i][j] = -1;
    fop (j,0,2) fop (i,0,N) dp[j][i] = (i == j ? 1 : 0);
    int n, m;
    string s;
    cin >> n >> m >> s;
    int all = 0, pre_min = 0;
    fop (i,0,m) {
    	all += (s[i] == ')' ? -1 : 1);
    	pre_min = min(pre_min, all);
	}
	int now = -pre_min;
	lli ans = 0;
	while (now + all <= n - m) {
		fop (i,0,n - m + 1) {
			ans = (ans + (solve(i, now) * solve(n - m - i, now + all) % mod)) % mod;
		}
		now++;
	}
	cout << ans << endl;
}


#include<bits/stdc++.h>
#define int long long
#define maxn
#define pb push_back
#define fi first
#define se second
#define fastio ios::sync_with_stdio(); cin.tie(0); cout.tie(0);
using namespace std;

const int mod = 1e9+7;
const int INF = INT_MAX;
const long double pi = 4*atan((long double)1);
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vii;

int dp[2002][2002];

signed main()
{
	fastio;
	int n, m;	cin >> n >> m;
	string str;	cin >> str;
	dp[1][1] = 1;
	dp[0][0] = 1;
	int temp = n-m;
	for (int i = 2; i <= 2000; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			if ((i - j) % 2 == 0)
			{
				if (i == j)	dp[i][j] = 1;
				else
				{
					dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1];
				}
				dp[i][j] %= mod;
			}
			else dp[i][j] = 0;
		}
	}
	int sum = 0;
	for (int i = 0; i < str.length(); i++)
	{
		if (str[i] == '(')	sum++;
		else sum--;
	}
	sum = abs(sum);
	int ans = 0;
	for (int i = 0; i <= temp; i++)
	{
		int rest = temp - i;
		for (int j = 0; j <= i; j++)
		{
			int demo = j + sum;
			if (demo > rest)	break;
			ans += dp[i][j] * dp[rest][demo];
			ans %= mod;
		}
	}
	cout << ans;
	return 0;
}


#include<bits/stdc++.h>
#define int long long
#define maxn
#define pb push_back
#define fi first
#define se second
#define fastio ios::sync_with_stdio(); cin.tie(0); cout.tie(0);
using namespace std;

const int mod = 1e9+7;
const int INF = INT_MAX;
const long double pi = 4*atan((long double)1);
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vii;

int dp[2002][2002][2];

signed main()
{
	fastio;
	int n, m;	cin >> n >> m;
	string str;	cin >> str;
	dp[1][1][0] = 1;
	dp[0][0][0] = 1;
	dp[0][0][1] = 1;
	int temp = n-m;
	for (int i = 2; i <= 2000; i++)
	{
		if (i % 2 == 0)	dp[i][0][1] =
		for (int j = 1; j <= i; j++)
		{
			if ((i - j) % 2 == 0)
			{
				if (i == j)	dp[i][j] = 1;
				else
				{
					dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1];
				}
				dp[i][j] %= mod;
			}
			else dp[i][j] = 0;
		}
	}
	int sum = 0;
	for (int i = 0; i < str.length(); i++)
	{
		if (str[i] == '(')	sum++;
		else sum--;
	}
	sum = abs(sum);
	int ans = 0;
	for (int i = 0; i <= temp; i++)
	{
		int rest = temp - i;
		for (int j = 0; j <= i; j++)
		{
			int demo = j + sum;
			if (demo > rest)	break;
			ans += dp[i][j] * dp[rest][demo];
			ans %= mod;
		}
	}
//	cout << dp[5][1] << endl;
	cout << ans;
	return 0;
}


#include<bits/stdc++.h>
#define int long long
#define maxn
#define pb push_back
#define fi first
#define se second
#define fastio ios::sync_with_stdio(); cin.tie(0); cout.tie(0);
using namespace std;

const int mod = 1e9+7;
const int INF = INT_MAX;
const long double pi = 4*atan((long double)1);
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vii;

int dp[2002][2002];

signed main()
{
	fastio;
	int n, m;	cin >> n >> m;
	string str;	cin >> str;
	dp[1][1] = 1;
	dp[0][0] = 1;
	int temp = n-m;
	for (int i = 2; i <= temp; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			if ((i - j) % 2 == 0)
			{
				if (i == j)	dp[i][j] = 1;
				else dp[i][j] = dp[i-2][j] * (i-1);
				dp[i][j] %= mod;
			}
			else dp[i][j] = 0;
		}
	}
	int sum = 0;
	for (int i = 0; i < str.length(); i++)
	{
		if (str[i] == '(')	sum++;
		else sum--;
	}
	sum = abs(sum);
	int ans = 0;
	for (int i = 0; i <= temp; i++)
	{
		int rest = temp - i;
		for (int j = 0; j <= i; j++)
		{
			int demo = j + sum;
			if (demo > rest)	break;
			ans += dp[i][j] * dp[rest][demo];
			ans %= mod;
		}
	}
	cout << ans;
	return 0;
}