Problem:
Score : 600 points

Problem Statement

There are N points in a two-dimensional plane. The initial coordinates of the i-th point are (x_i, y_i). Now, each point starts moving at a speed of 1 per second, in a direction parallel to the x- or y- axis. You are given a character d_i that represents the specific direction in which the i-th point moves, as follows:

If d_i = R, the i-th point moves in the positive x direction;

If d_i = L, the i-th point moves in the negative x direction;

If d_i = U, the i-th point moves in the positive y direction;

If d_i = D, the i-th point moves in the negative y direction.

You can stop all the points at some moment of your choice after they start moving (including the moment they start moving).
Then, let x_{max} and x_{min} be the maximum and minimum among the x-coordinates of the N points, respectively. Similarly, let y_{max} and y_{min} be the maximum and minimum among the y-coordinates of the N points, respectively.

Find the minimum possible value of (x_{max} - x_{min}) \times (y_{max} - y_{min}) and print it.

Constraints

1 \leq N \leq 10^5

-10^8 \leq x_i,\ y_i \leq 10^8

x_i and y_i are integers.

d_i is R, L, U, or D.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1 d_1
x_2 y_2 d_2
.
.
.
x_N y_N d_N

Output

Print the minimum possible value of (x_{max} - x_{min}) \times (y_{max} - y_{min}).

The output will be considered correct when its absolute or relative error from the judge's output is at most 10^{-9}.

Sample Input 1

2
0 3 D
3 0 L

Sample Output 1

0

After three seconds, the two points will meet at the origin. The value in question will be 0 at that moment.

Sample Input 2

5
-7 -10 U
7 -6 U
-8 7 D
-3 3 D
0 -6 R

Sample Output 2

97.5

The answer may not be an integer.

Sample Input 3

20
6 -10 R
-4 -9 U
9 6 D
-3 -2 R
0 7 D
4 5 D
10 -10 U
-1 -8 U
10 -6 D
8 -5 U
6 4 D
0 3 D
7 9 R
9 -4 R
3 10 D
1 9 U
1 -6 U
9 -8 R
6 7 D
7 -3 D

Sample Output 3

273

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Math;
using System.Text;

namespace Program
{
    public static class ABC130F
    {
        static public void Solve()
        {
            var N = NextInt;
            var pointList = new Tuple<long, long, string>[N];
            for (int i = 0; i < N; ++i)
            {
                pointList[i] = Tuple.Create(NextLong, NextLong, NextString);
            }
            var xList = new List<Tuple<long, int>>();
            var yList = new List<Tuple<long, int>>();
            for (int i = 0; i < N; ++i)
            {
                if (pointList[i].Item3 == "R")
                {
                    xList.Add(Tuple.Create(pointList[i].Item1, 1));
                    yList.Add(Tuple.Create(pointList[i].Item2, 0));
                }
                else if (pointList[i].Item3 == "L")
                {
                    xList.Add(Tuple.Create(pointList[i].Item1, -1));
                    yList.Add(Tuple.Create(pointList[i].Item2, 0));
                }
                else if (pointList[i].Item3 == "U")
                {
                    xList.Add(Tuple.Create(pointList[i].Item1, 0));
                    yList.Add(Tuple.Create(pointList[i].Item2, 1));
                }
                else
                {
                    xList.Add(Tuple.Create(pointList[i].Item1, 0));
                    yList.Add(Tuple.Create(pointList[i].Item2, -1));
                }
            }

            var xUpperMaxValid = xList.Where(e => e.Item2 == 1).Any();
            var xUpperMax = xUpperMaxValid ? xList.Where(e => e.Item2 == 1).Select(e => e.Item1).Max() : 0;
            var xDownerMaxValid = xList.Where(e => e.Item2 == -1).Any();
            var xDownerMax = xDownerMaxValid ? xList.Where(e => e.Item2 == -1).Select(e => e.Item1).Max() : 0;
            var xConstMaxValid = xList.Where(e => e.Item2 == 0).Any();
            var xConstMax = xConstMaxValid ? xList.Where(e => e.Item2 == 0).Select(e => e.Item1).Max() : 0;

            var xUpperMinValid = xList.Where(e => e.Item2 == 1).Any();
            var xUpperMin = xUpperMinValid ? xList.Where(e => e.Item2 == 1).Select(e => e.Item1).Min() : 0;
            var xDownerMinValid = xList.Where(e => e.Item2 == -1).Any();
            var xDownerMin = xDownerMinValid ? xList.Where(e => e.Item2 == -1).Select(e => e.Item1).Min() : 0;
            var xConstMinValid = xList.Where(e => e.Item2 == 0).Any();
            var xConstMin = xConstMinValid ? xList.Where(e => e.Item2 == 0).Select(e => e.Item1).Min() : 0;

            var yUpperMaxValid = yList.Where(e => e.Item2 == 1).Any();
            var yUpperMax = yUpperMaxValid ? yList.Where(e => e.Item2 == 1).Select(e => e.Item1).Max() : 0;
            var yDownerMaxValid = yList.Where(e => e.Item2 == -1).Any();
            var yDownerMax = yDownerMaxValid ? yList.Where(e => e.Item2 == -1).Select(e => e.Item1).Max() : 0;
            var yConstMaxValid = yList.Where(e => e.Item2 == 0).Any();
            var yConstMax = yConstMaxValid ? yList.Where(e => e.Item2 == 0).Select(e => e.Item1).Max() : 0;

            var yUpperMinValid = yList.Where(e => e.Item2 == 1).Any();
            var yUpperMin = yUpperMinValid ? yList.Where(e => e.Item2 == 1).Select(e => e.Item1).Min() : 0;
            var yDownerMinValid = yList.Where(e => e.Item2 == -1).Any();
            var yDownerMin = yDownerMinValid ? yList.Where(e => e.Item2 == -1).Select(e => e.Item1).Min() : 0;
            var yConstMinValid = yList.Where(e => e.Item2 == 0).Any();
            var yConstMin = yConstMinValid ? yList.Where(e => e.Item2 == 0).Select(e => e.Item1).Min() : 0;

            var xSmallMaxTime = 0.0;
            var xBigMinTime = 0.0;
            var ySmallMaxTime = 0.0;
            var yBigMinTime = 0.0;
            var xConst1Time = 0.0;
            var xConst2Time = 0.0;
            var xConst3Time = 0.0;
            var xConst4Time = 0.0;
            var yConst1Time = 0.0;
            var yConst2Time = 0.0;
            var yConst3Time = 0.0;
            var yConst4Time = 0.0;

            if (xUpperMaxValid && xDownerMaxValid)
            {
                xSmallMaxTime = xUpperMax >= xDownerMax ? 0 : (xDownerMax - xUpperMax) / 2.0;
            }
            if (xUpperMinValid && xDownerMinValid)
            {
                xBigMinTime = xDownerMin <= xUpperMin ? 0 : (xDownerMin - xUpperMin) / 2.0;
            }
            if (yUpperMaxValid && yDownerMaxValid)
            {
                ySmallMaxTime = yUpperMax >= yDownerMax ? 0 : (yDownerMax - yUpperMax) / 2.0;
            }
            if (yUpperMinValid && yDownerMinValid)
            {
                yBigMinTime = yDownerMin <= yUpperMin ? 0 : (yDownerMin - yUpperMin) / 2.0;
            }
            if (xConstMaxValid && xDownerMaxValid)
            {
                xConst1Time = xConstMax >= xDownerMax ? 0 : (xDownerMax - xConstMax);
            }
            if (xConstMaxValid && xUpperMaxValid)
            {
                xConst2Time = xConstMax <= xUpperMax ? 0 : (xConstMax - xUpperMax);
            }
            if (xConstMinValid && xDownerMinValid)
            {
                xConst3Time = xConstMin >= xDownerMin ? 0 : (xDownerMin - xConstMin);
            }
            if (xConstMinValid && xUpperMinValid)
            {
                xConst4Time = xConstMin <= xUpperMin ? 0 : (xConstMin - xUpperMin);
            }
            if (yConstMaxValid && yDownerMaxValid)
            {
                yConst1Time = yConstMax >= yDownerMax ? 0 : (yDownerMax - yConstMax);
            }
            if (yConstMaxValid && yUpperMaxValid)
            {
                yConst2Time = yConstMax <= yUpperMax ? 0 : (yConstMax - yUpperMax);
            }
            if (yConstMinValid && yDownerMinValid)
            {
                yConst3Time = yConstMin >= yDownerMin ? 0 : (yDownerMin - yConstMin);
            }
            if (yConstMinValid && yUpperMinValid)
            {
                yConst4Time = yConstMin <= yUpperMin ? 0 : (yConstMin - yUpperMin);
            }

            Func<double, double> xMaxAtTime = time =>
            {
                double tmp = xConstMax;
                if (xDownerMaxValid && xUpperMaxValid)
                {
                    tmp = Max(xDownerMax - time, xUpperMax + time);
                }
                else if (!xDownerMaxValid && xUpperMaxValid)
                {
                    tmp = xUpperMax + time;
                }
                else if (xDownerMaxValid && !xUpperMaxValid)
                {
                    tmp = xDownerMax - time;
                }
                return xConstMaxValid ? Max(xConstMax, tmp) : tmp;
            };

            Func<double, double> xMinAtTime = time =>
            {
                double tmp = xConstMin;
                if (xDownerMinValid && xUpperMinValid)
                {
                    tmp = Min(xDownerMin - time, xUpperMin + time);
                }
                else if (!xDownerMinValid && xUpperMinValid)
                {
                    tmp = xUpperMin + time;
                }
                else if (xDownerMinValid && !xUpperMinValid)
                {
                    tmp = xDownerMin - time;
                }
                return xConstMinValid ? Min(xConstMin, tmp) : tmp;
            };

            Func<double, double> yMaxAtTime = time =>
            {
                double tmp = yConstMax;
                if (yDownerMaxValid && yUpperMaxValid)
                {
                    tmp = Max(yDownerMax - time, yUpperMax + time);
                }
                else if (!yDownerMaxValid && yUpperMaxValid)
                {
                    tmp = yUpperMax + time;
                }
                else if (yDownerMaxValid && !yUpperMaxValid)
                {
                    tmp = yDownerMax - time;
                }
                return yConstMaxValid ? Max(yConstMax, tmp) : tmp;
            };

            Func<double, double> yMinAtTime = time =>
            {
                double tmp = yConstMin;
                if (yDownerMinValid && yUpperMinValid)
                {
                    tmp = Min(yDownerMin - time, yUpperMin + time);
                }
                else if (!yDownerMinValid && yUpperMinValid)
                {
                    tmp = yUpperMin + time;
                }
                else if (yDownerMinValid && !yUpperMinValid)
                {
                    tmp = yDownerMin - time;
                }
                return yConstMinValid ? Min(yConstMin, tmp) : tmp;
            };

            var ans = double.MaxValue;

            ans = Min(ans, (xMaxAtTime(xSmallMaxTime) - xMinAtTime(xSmallMaxTime)) * (yMaxAtTime(xSmallMaxTime) - yMinAtTime(xSmallMaxTime)));
            ans = Min(ans, (xMaxAtTime(xBigMinTime) - xMinAtTime(xBigMinTime)) * (yMaxAtTime(xBigMinTime) - yMinAtTime(xBigMinTime)));
            ans = Min(ans, (xMaxAtTime(ySmallMaxTime) - xMinAtTime(ySmallMaxTime)) * (yMaxAtTime(ySmallMaxTime) - yMinAtTime(ySmallMaxTime)));
            ans = Min(ans, (xMaxAtTime(yBigMinTime) - xMinAtTime(yBigMinTime)) * (yMaxAtTime(yBigMinTime) - yMinAtTime(yBigMinTime)));
            ans = Min(ans, (xMaxAtTime(xConst1Time) - xMinAtTime(xConst1Time)) * (yMaxAtTime(xConst1Time) - yMinAtTime(xConst1Time)));
            ans = Min(ans, (xMaxAtTime(xConst2Time) - xMinAtTime(xConst2Time)) * (yMaxAtTime(xConst2Time) - yMinAtTime(xConst2Time)));
            ans = Min(ans, (xMaxAtTime(xConst3Time) - xMinAtTime(xConst3Time)) * (yMaxAtTime(xConst3Time) - yMinAtTime(xConst3Time)));
            ans = Min(ans, (xMaxAtTime(xConst4Time) - xMinAtTime(xConst4Time)) * (yMaxAtTime(xConst4Time) - yMinAtTime(xConst4Time)));
            ans = Min(ans, (xMaxAtTime(yConst1Time) - xMinAtTime(yConst1Time)) * (yMaxAtTime(yConst1Time) - yMinAtTime(yConst1Time)));
            ans = Min(ans, (xMaxAtTime(yConst2Time) - xMinAtTime(yConst2Time)) * (yMaxAtTime(yConst2Time) - yMinAtTime(yConst2Time)));
            ans = Min(ans, (xMaxAtTime(yConst3Time) - xMinAtTime(yConst3Time)) * (yMaxAtTime(yConst3Time) - yMinAtTime(yConst3Time)));
            ans = Min(ans, (xMaxAtTime(yConst4Time) - xMinAtTime(yConst4Time)) * (yMaxAtTime(yConst4Time) - yMinAtTime(yConst4Time)));

            Console.WriteLine(ans);
        }

        static public void Main(string[] args)
        {
            if (args.Length == 0)
            {
                var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
                Console.SetOut(sw);
            }
            Solve();
            Console.Out.Flush();
        }
        static Random rand = new Random();
        static class Console_
        {
            private static Queue<string> param = new Queue<string>();
            public static string NextString()
            {
                if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item);
                return param.Dequeue();
            }
        }
        static int NextInt => int.Parse(Console_.NextString());
        static long NextLong => long.Parse(Console_.NextString());
        static double NextDouble => double.Parse(Console_.NextString());
        static string NextString => Console_.NextString();
        static List<int> NextIntList(int N) => Enumerable.Repeat(0, N).Select(_ => NextInt).ToList();
        static List<long> NextLongList(int N) => Enumerable.Repeat(0, N).Select(_ => NextLong).ToList();
        static List<double> NextDoubleList(int N) => Enumerable.Repeat(0, N).Select(_ => NextDouble).ToList();
        static List<string> NextStringList(int N) => Enumerable.Repeat(0, N).Select(_ => NextString).ToList();
        static IEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => x.OrderBy(_ => rand.Next());
        static IEnumerable<T> Repeat<T>(T v, int n) => Enumerable.Repeat<T>(v, n);
        static List<T> Sort<T>(List<T> l) where T : IComparable
        {
            var tmp = l.ToArray(); Array.Sort(tmp); return tmp.ToList();
        }
        static List<T> Sort<T>(List<T> l, Comparison<T> comp) where T : IComparable
        {
            var tmp = l.ToArray(); Array.Sort(tmp, comp); return tmp.ToList();
        }
        static List<T> RevSort<T>(List<T> l) where T : IComparable
        {
            var tmp = l.ToArray(); Array.Sort(tmp, (x, y) => y.CompareTo(x)); return tmp.ToList();
        }
        static List<T> RevSort<T>(List<T> l, Comparison<T> comp) where T : IComparable
        {
            var tmp = l.ToArray(); Array.Sort(tmp, (x, y) => comp(y, x)); return tmp.ToList();
        }
        static IEnumerable<long> Prime(long x)
        {
            if (x < 2) yield break;
            yield return 2;
            var halfx = x / 2;
            var table = new bool[halfx + 1];
            var max = (long)(Math.Sqrt(x) / 2);
            for (long i = 1; i <= max; ++i)
            {
                if (table[i]) continue;
                var add = 2 * i + 1;
                yield return add;
                for (long j = 2 * i * (i + 1); j <= halfx; j += add) table[j] = true;
            }
            for (long i = max + 1; i <= halfx; ++i) if (!table[i] && 2 * i + 1 <= x) yield return 2 * i + 1;
        }
        static IEnumerable<long> Divisor(long x)
        {
            if (x < 1) yield break;
            var max = (long)Math.Sqrt(x);
            for (long i = 1; i <= max; ++i)
            {
                if (x % i != 0) continue;
                yield return i;
                if (i != x / i) yield return x / i;
            }
        }
        static long GCD(long a, long b)
        {
            while (b > 0) { var tmp = b; b = a % b; a = tmp; }
            return a;
        }
        class PQ<T> where T : IComparable
        {
            private List<T> h;
            private Comparison<T> c;
            public PQ(int cap, Comparison<T> c, bool asc = true) { h = new List<T>(cap); this.c = asc ? c : (x, y) => c(y, x); }
            public PQ(Comparison<T> c, bool asc = true) { h = new List<T>(); this.c = asc ? c : (x, y) => c(y, x); }
            public PQ(int cap, bool asc = true) : this(cap, (x, y) => x.CompareTo(y), asc) { }
            public PQ(bool asc = true) : this((x, y) => x.CompareTo(y), asc) { }
            public void Push(T v)
            {
                var i = h.Count;
                h.Add(v);
                while (i > 0)
                {
                    var ni = (i - 1) / 2;
                    if (c(v, h[ni]) >= 0) break;
                    h[i] = h[ni]; i = ni;
                }
                h[i] = v;
            }
            public T Peek => h[0];
            public int Count => h.Count;
            public T Pop()
            {
                var r = h[0];
                var v = h[h.Count - 1];
                h.RemoveAt(h.Count - 1);
                if (h.Count == 0) return r;
                var i = 0;
                while (i * 2 + 1 < h.Count)
                {
                    var i1 = i * 2 + 1;
                    var i2 = i * 2 + 2;
                    if (i2 < h.Count && c(h[i1], h[i2]) > 0) i1 = i2;
                    if (c(v, h[i1]) <= 0) break;
                    h[i] = h[i1]; i = i1;
                }
                h[i] = v;
                return r;
            }
        }
        class PQ<TKey, TValue> where TKey : IComparable
        {
            private PQ<Tuple<TKey, TValue>> q;
            public PQ(int cap, Comparison<TKey> c, bool asc = true) { q = new PQ<Tuple<TKey, TValue>>(cap, (x, y) => c(x.Item1, y.Item1), asc); }
            public PQ(Comparison<TKey> c, bool asc = true) { q = new PQ<Tuple<TKey, TValue>>((x, y) => c(x.Item1, y.Item1), asc); }
            public PQ(int cap, bool asc = true) : this(cap, (x, y) => x.CompareTo(y), asc) { }
            public PQ(bool asc = true) : this((x, y) => x.CompareTo(y), asc) { }
            public void Push(TKey k, TValue v) => q.Push(Tuple.Create(k, v));
            public Tuple<TKey, TValue> Peek => q.Peek;
            public int Count => q.Count;
            public Tuple<TKey, TValue> Pop() => q.Pop();
        }
        class Mod
        {
            static public long _mod = 1000000007;
            private long _val = 0;
            public Mod(long x) { _val = x % _mod; }
            static public implicit operator Mod(long x) => new Mod(x);
            static public explicit operator long(Mod x) => x._val;
            static public Mod operator +(Mod x) => x._val;
            static public Mod operator -(Mod x) => -x._val;
            static public Mod operator ++(Mod x) => x._val + 1;
            static public Mod operator --(Mod x) => x._val - 1;
            static public Mod operator +(Mod x, Mod y) => (x._val + y._val) % _mod;
            static public Mod operator -(Mod x, Mod y) => ((((x._val - y._val) % _mod) + _mod) % _mod);
            static public Mod operator *(Mod x, Mod y) => (x._val * y._val) % _mod;
            static public Mod operator /(Mod x, Mod y) => (x._val * Inverse(y._val)) % _mod;
            static public bool operator ==(Mod x, Mod y) => x._val == y._val;
            static public bool operator !=(Mod x, Mod y) => x._val != y._val;
            static public bool operator <(Mod x, Mod y) => x._val < y._val;
            static public bool operator >(Mod x, Mod y) => x._val > y._val;
            static public bool operator <=(Mod x, Mod y) => x._val <= y._val;
            static public bool operator >=(Mod x, Mod y) => x._val >= y._val;
            static public Mod Pow(Mod x, long y)
            {
                Mod a = 1;
                while (y != 0)
                {
                    if ((y & 1) == 1) a *= x;
                    x *= x;
                    y >>= 1;
                }
                return a;
            }
            static public long Inverse(long x)
            {
                long b = _mod, r = 1, u = 0, t = 0;
                while (b > 0)
                {
                    var q = x / b;
                    t = u; u = r - q * u; r = t;
                    t = b; b = x - q * b; x = t;
                }
                return r < 0 ? r + _mod : r;
            }
            override public bool Equals(object obj) => obj == null ? false : _val == ((Mod)obj)._val;
            public bool Equals(Mod obj) => obj == null ? false : _val == obj._val;
            public override int GetHashCode() => _val.GetHashCode();
            public override string ToString() => _val.ToString();
            static private List<Mod> _fact = new List<Mod>();
            static private List<Mod> _ifact = new List<Mod>();
            static private void Build(int n)
            {
                if (n >= _fact.Count)
                    for (int i = _fact.Count; i <= n; ++i)
                        if (i == 0L) { _fact.Add(1); _ifact.Add(1); }
                        else { _fact.Add(_fact[i - 1] * i); _ifact.Add(_ifact[i - 1] * Mod.Pow(i, _mod - 2)); }
            }
            static public Mod Comb(int n, int k)
            {
                Build(n);
                if (n == 0 && k == 0) return 1;
                if (n < k || n < 0) return 0;
                return _ifact[n - k] * _ifact[k] * _fact[n];
            }
        }
        class Mat<T>
        {
            private T[,] m;
            public Mat(T[,] v) { m = (T[,])v.Clone(); }
            static public implicit operator Mat<T>(T[,] v) => new Mat<T>(v);
            public T this[int r, int c] { get { return m[r, c]; } set { m[r, c] = value; } }
            static public Mat<T> operator +(Mat<T> a, T x)
            {
                var tm = (T[,])a.m.Clone();
                for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] += (dynamic)x;
                return new Mat<T>(tm);
            }
            static public Mat<T> operator +(Mat<T> a, Mat<T> b)
            {
                var tm = (T[,])a.m.Clone();
                for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] += (dynamic)b[r, c];
                return new Mat<T>(tm);
            }
            static public Mat<T> operator -(Mat<T> a, T x)
            {
                var tm = (T[,])a.m.Clone();
                for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] -= (dynamic)x;
                return new Mat<T>(tm);
            }
            static public Mat<T> operator -(Mat<T> a, Mat<T> b)
            {
                var tm = (T[,])a.m.Clone();
                for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] -= (dynamic)b[r, c];
                return new Mat<T>(tm);
            }
            static public Mat<T> operator *(Mat<T> a, T x)
            {
                var tm = (T[,])a.m.Clone();
                for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] *= (dynamic)x;
                return new Mat<T>(tm);
            }
            static public Mat<T> operator *(Mat<T> a, Mat<T> b)
            {
                var nr = a.m.GetLength(0);
                var nc = b.m.GetLength(1);
                var tm = new T[nr, nc];
                for (int i = 0; i < nr; ++i) for (int j = 0; j < nc; ++j) tm[i, j] = (dynamic)0;
                for (int r = 0; r < nr; ++r) for (int c = 0; c < nc; ++c) for (int i = 0; i < a.m.GetLength(1); ++i) tm[r, c] += a[r, i] * (dynamic)b[i, c];
                return new Mat<T>(tm);
            }
            static public Mat<T> Pow(Mat<T> x, long y)
            {
                var n = x.m.GetLength(0);
                var t = (Mat<T>)new T[n, n];
                for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) t[i, j] = (dynamic)(i == j ? 1 : 0);
                while (y != 0)
                {
                    if ((y & 1) == 1) t *= x;
                    x *= x;
                    y >>= 1;
                }
                return t;
            }
        }
        static Mat<T> Pow<T>(Mat<T> x, long y) => Mat<T>.Pow(x, y);
        static Mod Pow(Mod x, long y) => Mod.Pow(x, y);
        static long Pow(long x, long y)
        {
            long a = 1;
            while (y != 0)
            {
                if ((y & 1) == 1) a *= x;
                x *= x;
                y >>= 1;
            }
            return a;
        }
        static List<long> _fact = new List<long>();
        static void _Build(int n)
        {
            if (n >= _fact.Count)
                for (int i = _fact.Count; i <= n; ++i)
                    if (i == 0L) _fact.Add(1);
                    else _fact.Add(_fact[i - 1] * i);
        }
        static long Comb(int n, int k)
        {
            _Build(n);
            if (n == 0 && k == 0) return 1;
            if (n < k || n < 0) return 0;
            return _fact[n] / _fact[k] / _fact[n - k];
        }
    }
}