using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace Codeforces
{
    class E
    {
        private static ThreadStart  s_threadStart = new E().Go;

        class Point
        {
            public int X, Y;
            public bool Keep;
        }

        long[] F;

        private void Go()
        {
            long mod = 1000000007;

            int n = GetInt();
            Point[] points = new Point[n];
            for (int i = 0; i < n; i++)
            {
                points[i] = new Point() { X = GetInt(), Y = GetInt() };
            }

            F = new long[2*n + 1];
            F[0] = 1;
            for (int i = 1; i <= 2 * n; i++)
                F[i] = (F[i - 1] * i) % mod;

            Dictionary<int, List<int>> xDict = new Dictionary<int, List<int>>();
            Dictionary<int, List<int>> yDict = new Dictionary<int, List<int>>();
            for(int i = 0; i < n; i++)
            {
                List<int> list;
                if (!xDict.TryGetValue(points[i].X, out list))
                    list = xDict[points[i].X] = new List<int>();

                list.Add(i);

                if (!yDict.TryGetValue(points[i].Y, out list))
                    list = yDict[points[i].Y] = new List<int>();

                list.Add(i);
            }

            long ans = 1;

            Queue<int> queue = new Queue<int>();
            while (xDict.Count > 0)
            {
                int k = 0;
                int m = 0;
                var pair = xDict.First();
                queue.Enqueue(pair.Value[0]);

                HashSet<int> xDir = new HashSet<int>();
                HashSet<int> yDir = new HashSet<int>();
                HashSet<int> pSet = new HashSet<int>();

                while (queue.Count > 0)
                {
                    int pp = queue.Dequeue();
                    Point point = points[pp];
                    pSet.Add(pp);
                    xDir.Add(point.X);
                    yDir.Add(point.Y);
                    if (xDict.ContainsKey(point.X))
                    {
                        foreach (int z in xDict[point.X])
                            if (z != pp)
                                queue.Enqueue(z);
                    }
                    if (yDict.ContainsKey(point.Y))
                    {
                        foreach (int z in yDict[point.Y])
                            if (z != pp)
                                queue.Enqueue(z);
                    }
                    xDict.Remove(point.X);
                    yDict.Remove(point.Y);
                }

                ans *= Bin(xDir.Count() + yDir.Count(), pSet.Count(), mod);
                ans %= mod;
            }

            Wl(ans);
        }

        long Bin(long n, long k, long mod)
        {
            long ans = 0;
            for (int i = 0; i <= k; i++)
            {
                long add = F[n];
                add *= Inv(F[i], mod);
                add %= mod;
                add *= Inv(F[n - i], mod);
                add %= mod;
                ans += add;
                ans %= mod;
            }
            return ans;
        }

        public static long Pow(long a, long n, long mod)
        {
            long res = 1L;
            while (n > 0)
            {
                if ((n & 1) != 0)
                    res = (res * a) % mod;
                a = (a * a) % mod;
                n >>= 1;
            }
            return res;
        }

        public static long Inv(long a, long mod)
        {
            return Pow(a, mod - 2, mod);
        }

        #region Template

        private static StringBuilder output = new StringBuilder();

        public static void Main(string[] args)
        {
            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            output.Length = 0;
            Thread main = new Thread(new ThreadStart(s_threadStart), 512 * 1024 * 1024);
            timer.Start();
            main.Start();
            main.Join();
            Console.Write(output);
            timer.Stop();
            Console.Error.WriteLine(timer.ElapsedMilliseconds);
        }

        private static IEnumerator<string> ioEnum;
        private static string GetString()
        {
            do
            {
                while (ioEnum == null || !ioEnum.MoveNext())
                {
                    ioEnum = Console.ReadLine().Split().AsEnumerable().GetEnumerator();
                }
            } while (string.IsNullOrEmpty(ioEnum.Current));

            return ioEnum.Current;
        }

        private static int GetInt()
        {
            return int.Parse(GetString());
        }

        private static long GetLong()
        {
            return long.Parse(GetString());
        }

        private static double GetDouble()
        {
            return double.Parse(GetString());
        }

        private static List<int> GetIntArr(int n)
        {
            List<int> ret = new List<int>(n);
            for (int i = 0; i < n; i++)
            {
                ret.Add(GetInt());
            }
            return ret;
        }

        private static void Wl<T>(T o)
        {
            W(o);
            output.Append(Console.Out.NewLine);
        }

        private static void Wl<T>(IEnumerable<T> enumerable)
        {
            W(enumerable);
            output.Append(Console.Out.NewLine);
        }

        private static void W<T>(T o)
        {
            if (o is double)
            {
                Wd((o as double?).Value, "");
            }
            else if (o is float)
            {
                Wd((o as float?).Value, "");
            }
            else
                output.Append(o.ToString());
        }

        private static void W<T>(IEnumerable<T> enumerable)
        {
            W(string.Join(" ", enumerable.Select(e => e.ToString()).ToArray()));
        }

        private static void Wd(double d, string format)
        {
            W(d.ToString(format, CultureInfo.InvariantCulture));
        }

        #endregion
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace Codeforces
{
    class E
    {
        private static ThreadStart  s_threadStart = new E().Go;

        class Point
        {
            public int X, Y;
            public bool Keep;
        }

        long[] F;

        private void Go()
        {
            long mod = 1000000007;

            int n = GetInt();
            Point[] points = new Point[n];
            for (int i = 0; i < n; i++)
            {
                points[i] = new Point() { X = GetInt(), Y = GetInt() };
            }

            F = new long[n + 1];
            F[0] = 1;
            for (int i = 1; i <= n; i++)
                F[i] = (F[i - 1] * i) % mod;

            Dictionary<int, List<int>> xDict = new Dictionary<int, List<int>>();
            Dictionary<int, List<int>> yDict = new Dictionary<int, List<int>>();
            for(int i = 0; i < n; i++)
            {
                List<int> list;
                if (!xDict.TryGetValue(points[i].X, out list))
                    list = xDict[points[i].X] = new List<int>();

                list.Add(i);

                if (!yDict.TryGetValue(points[i].Y, out list))
                    list = yDict[points[i].Y] = new List<int>();

                list.Add(i);
            }

            long ans = 1;

            Queue<int> queue = new Queue<int>();
            while (xDict.Count > 0)
            {
                int k = 0;
                int m = 0;
                var pair = xDict.First();
                queue.Enqueue(pair.Value[0]);

                HashSet<int> xDir = new HashSet<int>();
                HashSet<int> yDir = new HashSet<int>();
                HashSet<int> pSet = new HashSet<int>();

                while (queue.Count > 0)
                {
                    int pp = queue.Dequeue();
                    Point point = points[pp];
                    pSet.Add(pp);
                    xDir.Add(point.X);
                    yDir.Add(point.Y);
                    if (xDict.ContainsKey(point.X))
                    {
                        foreach (int z in xDict[point.X])
                            if (z != pp)
                                queue.Enqueue(z);
                    }
                    if (yDict.ContainsKey(point.Y))
                    {
                        foreach (int z in yDict[point.Y])
                            if (z != pp)
                                queue.Enqueue(z);
                    }
                    xDict.Remove(point.X);
                    yDict.Remove(point.Y);
                }

                ans *= Bin(xDir.Count() + yDir.Count(), pSet.Count(), mod);
                ans %= mod;
            }

            Wl(ans);
        }

        long Bin(long n, long k, long mod)
        {
            long ans = 0;
            for (int i = 0; i <= k; i++)
            {
                long add = F[n];
                add *= Inv(F[i], mod);
                add %= mod;
                add *= Inv(F[n - i], mod);
                add %= mod;
                ans += add;
                ans %= mod;
            }
            return ans;
        }

        public static long Pow(long a, long n, long mod)
        {
            long res = 1L;
            while (n > 0)
            {
                if ((n & 1) != 0)
                    res = (res * a) % mod;
                a = (a * a) % mod;
                n >>= 1;
            }
            return res;
        }

        public static long Inv(long a, long mod)
        {
            return Pow(a, mod - 2, mod);
        }

        #region Template

        private static StringBuilder output = new StringBuilder();

        public static void Main(string[] args)
        {
            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            output.Length = 0;
            Thread main = new Thread(new ThreadStart(s_threadStart), 512 * 1024 * 1024);
            timer.Start();
            main.Start();
            main.Join();
            Console.Write(output);
            timer.Stop();
            Console.Error.WriteLine(timer.ElapsedMilliseconds);
        }

        private static IEnumerator<string> ioEnum;
        private static string GetString()
        {
            do
            {
                while (ioEnum == null || !ioEnum.MoveNext())
                {
                    ioEnum = Console.ReadLine().Split().AsEnumerable().GetEnumerator();
                }
            } while (string.IsNullOrEmpty(ioEnum.Current));

            return ioEnum.Current;
        }

        private static int GetInt()
        {
            return int.Parse(GetString());
        }

        private static long GetLong()
        {
            return long.Parse(GetString());
        }

        private static double GetDouble()
        {
            return double.Parse(GetString());
        }

        private static List<int> GetIntArr(int n)
        {
            List<int> ret = new List<int>(n);
            for (int i = 0; i < n; i++)
            {
                ret.Add(GetInt());
            }
            return ret;
        }

        private static void Wl<T>(T o)
        {
            W(o);
            output.Append(Console.Out.NewLine);
        }

        private static void Wl<T>(IEnumerable<T> enumerable)
        {
            W(enumerable);
            output.Append(Console.Out.NewLine);
        }

        private static void W<T>(T o)
        {
            if (o is double)
            {
                Wd((o as double?).Value, "");
            }
            else if (o is float)
            {
                Wd((o as float?).Value, "");
            }
            else
                output.Append(o.ToString());
        }

        private static void W<T>(IEnumerable<T> enumerable)
        {
            W(string.Join(" ", enumerable.Select(e => e.ToString()).ToArray()));
        }

        private static void Wd(double d, string format)
        {
            W(d.ToString(format, CultureInfo.InvariantCulture));
        }

        #endregion
    }
}


using System;
using System.Globalization;
using System.IO;
using System.Text;

namespace Guess_the_Tree
{
    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 = int.Parse(reader.ReadLine());

            string[] ss = reader.ReadLine().Split(' ');
           int[] nn = new int[n];
            for (int i = 0; i < n; i++)
            {
                nn[i] = int.Parse(ss[i]);
            }

            Array.Sort(nn);

            bool[] used = new bool[n];
bool ok = true;
            for (int i = 0; i < n; i++)
            {
                if (nn[i]>1)
                {
                    int count = nn[i] - 1;
                    int p = 0;
                    for (int j = i; j >=0; j--)
                    {
                        if (!used[j] && nn[j]<=count)
                        {
                            if (p == 0 && nn[j] == count)
                                continue;
                            used[j] = true;
                            count -= nn[j];
                            p++;
                        }
                        if (count==0)
                            break;
                    }
                    if (count!=0)
                    {
                        ok = false;
                        break;
                    }
                }
            }

            writer.WriteLine("{0}", ok ? "YES" : "NO");
            writer.Flush();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProgrammingContest.Codeforces.Round63
{
    class D
    {
        int[,,] win = new int[4,500, 500];
        int offset = 200;
        int[] vx, vy;
        int d;

        bool isLose(int x, int y) { return d*d <= x*x + y*y; }

        bool solve(int reflect, int x, int y)
        {
            if (isLose(x, y))
                return true;

            if (win[reflect, x + offset, y + offset] != 0)
                return win[reflect, x + offset, y + offset] > 0;

            if (reflect % 2 == 1)
            {
                if (!solve(reflect >> 1, y, x))
                    return (win[reflect, x + offset, y + offset] = 1) > 0;
            }

            int r = ((reflect % 2) << 1) | (reflect >> 1);
            for (int i = 0; i < vx.Length; i++)
                if (!solve(r, x + vx[i], y + vy[i]))
                    return (win[reflect, x + offset, y + offset] = 1) > 0;

            return (win[reflect, x + offset, y + offset] = -1) > 0;
        }

        D()
        {
            var xs = Array.ConvertAll(Console.ReadLine().Split(' '), sss => int.Parse(sss));
            int x = xs[0],
                y = xs[1],
                n = xs[2];
            d = xs[3];
            vx = new int[n];
            vy = new int[n];
            for (int i = 0; i < n; i++)
            {
                var ys = Array.ConvertAll(Console.ReadLine().Split(' '), sss => int.Parse(sss));
                vx[i] = ys[0];
                vy[i] = ys[1];
            }
            Console.WriteLine(solve(3, x, y) ? "Anton" : "Dasha");
        }

        public static void Main()
        {
            new D();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProgrammingContest.Codeforces.Round63
{
    class D
    {
        int[,,] win = new int[4,500, 500];
        int offset = 200;
        int[] vx, vy;
        int d;

        bool isLose(int x, int y) { return d*d < x*x + y*y; }

        bool solve(int reflect, int x, int y)
        {
            if (isLose(x, y))
                return true;

            if (win[reflect, x + offset, y + offset] != 0)
                return win[reflect, x + offset, y + offset] > 0;

            if (reflect % 2 == 1)
            {
                if (!solve(reflect >> 1, y, x))
                    return (win[reflect, x + offset, y + offset] = 1) > 0;
            }

            int r = ((reflect % 2) << 1) | (reflect >> 1);
            for (int i = 0; i < vx.Length; i++)
                if (!solve(r, x + vx[i], y + vy[i]))
                    return (win[reflect, x + offset, y + offset] = 1) > 0;

            return (win[reflect, x + offset, y + offset] = -1) > 0;
        }

        D()
        {
            var xs = Array.ConvertAll(Console.ReadLine().Split(' '), sss => int.Parse(sss));
            int x = xs[0],
                y = xs[1],
                n = xs[2];
            d = xs[3];
            vx = new int[n];
            vy = new int[n];
            for (int i = 0; i < n; i++)
            {
                var ys = Array.ConvertAll(Console.ReadLine().Split(' '), sss => int.Parse(sss));
                vx[i] = ys[0];
                vy[i] = ys[1];
            }
            Console.WriteLine(solve(3, x, y) ? "Anton" : "Dasha");
        }

        public static void Main()
        {
            new D();
        }
    }
}


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

namespace Cutlet
{
    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)
        {
            Solve(args);
            writer.Flush();
        }

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

            var l = new int[k];
            var r = new int[k];
            for (int i = 0; i < k; i++)
            {
                l[i] = Next();
                r[i] = Next();
            }

            List<Interval>[] dp;
            dp = new List<Interval>[2*k + 1];

            for (int i = 0; i < dp.Length; i++)
            {
                dp[i] = new List<Interval>();
            }
            dp[0].Add(new Interval(0, 0));

            int prev = 0;
            for (int i = 0; i < k; i++)
            {
                var next = new List<Interval>[dp.Length];
                for (int ii = 0; ii < dp.Length; ii++)
                {
                    next[ii] = new List<Interval>();
                }

                int delta = l[i] - prev;
                for (int index = 0; index < dp.Length; index++)
                {
                    if (index%2 == 0)
                    {
                        List<Interval> t = dp[index];
                        foreach (Interval interval in t)
                        {
                            interval.l += delta;
                            interval.r += delta;
                        }
                    }
                }
                delta = r[i] - l[i];
                for (int ii = 0; ii < dp.Length; ii++)
                {
                    if (ii%2 == 0)
                    {
                        foreach (Interval interval in dp[ii])
                        {
                            next[ii].Add(new Interval(interval.l + delta, interval.r + delta));
                            next[ii + 1].Add(new Interval(interval.l, interval.r + delta));
                            next[ii + 2].Add(new Interval(interval.l, interval.r + delta));
                        }
                    }
                    else
                    {
                        foreach (Interval interval in dp[ii])
                        {
                            next[ii].Add(new Interval(interval.l, interval.r));
                            next[ii + 1].Add(new Interval(interval.l, interval.r + delta));
                            next[ii + 2].Add(new Interval(interval.l, interval.r + delta));
                        }
                    }
                }

                prev = r[i];
                for (int index = 0; index < dp.Length; index++)
                {
                    dp[index].Clear();

                    Interval pr = null;
                    foreach (Interval interval in next[index].OrderBy(t => t.l))
                    {
                        if (interval.l > n)
                            break;
                        if (pr != null && pr.r >= interval.l)
                        {
                            pr.r = Math.Max(pr.r, interval.r);
                        }
                        else
                        {
                            if (pr != null && !Find(dp, pr, index))
                                dp[index].Add(pr);
                            pr = interval;
                        }
                    }
                    if (pr != null && !Find(dp, pr, index))
                        dp[index].Add(pr);
                }
            }

            {
                int delta = 2*n - prev;
                for (int index = 0; index < dp.Length; index++)
                {
                    if (index%2 == 0)
                    {
                        List<Interval> t = dp[index];
                        foreach (Interval interval in t)
                        {
                            interval.l += delta;
                            interval.r += delta;
                        }
                    }
                }
            }

            for (int i = 0; i < dp.Length; i++)
            {
                foreach (Interval interval in dp[i])
                {
                    if (interval.l <= n && interval.r >= n)
                    {
                        writer.WriteLine("Full");
                        writer.WriteLine(i);
                        return;
                    }
                }
            }

            writer.WriteLine("Hungry");
        }

        private static bool Find(List<Interval>[] dp, Interval value, int index)
        {
            for (int i = index - 2; i >= 0; i--)
            {
                int ind = dp[i].BinarySearch(value, value);
                if (ind < 0)
                {
                    ind = (~ind) - 1;
                    if (ind > 0 && dp[i][ind].r >= value.r)
                    {
                        return true;
                    }
                }
                else
                {
                    if (dp[i][ind].r >= value.r)
                        return true;
                }
            }

            return false;
        }

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

        #region Nested type: Interval

        private class Interval : IComparer<Interval>
        {
            public int l, r;

            public Interval(int l, int r)
            {
                this.l = l;
                this.r = r;
            }

            #region IComparer<Interval> Members

            public int Compare(Interval x, Interval y)
            {
                return x.l.CompareTo(y.l);
            }

            #endregion
        }

        #endregion
    }
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace Temp
{
    internal class PointInt
    {
        public long X;

        public long Y;

        public PointInt(long x, long y)
        {
            this.X = x;
            this.Y = y;
        }

        public PointInt(PointInt head)
            : this(head.X, head.Y)
        {
        }

        public static PointInt operator +(PointInt a, PointInt b)
        {
            return new PointInt(a.X + b.X, a.Y + b.Y);
        }

        public static PointInt operator -(PointInt a, PointInt b)
        {
            return new PointInt(a.X - b.X, a.Y - b.Y);
        }

        public static PointInt operator *(PointInt a, long k)
        {
            return new PointInt(k * a.X, k * a.Y);
        }

        public static PointInt operator *(long k, PointInt a)
        {
            return new PointInt(k * a.X, k * a.Y);
        }

        public bool IsInsideRectangle(long l, long b, long r, long t)
        {
            return (l <= X) && (X <= r) && (b <= Y) && (Y <= t);
        }

        public bool Equals(PointInt other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return other.X == this.X && other.Y == this.Y;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != typeof(PointInt))
            {
                return false;
            }
            return Equals((PointInt)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (this.X.GetHashCode() * 397) ^ this.Y.GetHashCode();
            }
        }
    }

    internal class LineInt
    {
        public LineInt(PointInt a, PointInt b)
        {
            A = a.Y - b.Y;
            B = b.X - a.X;
            C = a.X * b.Y - a.Y * b.X;
        }

        public long A, B, C;

        public bool ContainsPoint(PointInt p)
        {
            return A * p.X + B * p.Y + C == 0;
        }

        public int Sign(PointInt p)
        {
            return Math.Sign(A * p.X + B * p.Y + C);
        }
    }

    internal static class Geometry
    {
        public static long VectInt(PointInt a, PointInt b)
        {
            return a.X * b.Y - a.Y * b.X;
        }

        public static long VectInt(PointInt a, PointInt b, PointInt c)
        {
            return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);
        }
    }

    internal class MatrixInt
    {
        private readonly long[,] m_Matrix;

        public int Size
        {
            get
            {
                return m_Matrix.GetLength(0);
            }
        }

        public long Mod { get; private set; }

        public MatrixInt(int size, long mod = 0)
        {
            m_Matrix = new long[size,size];
            Mod = mod;
        }

        public MatrixInt(long[,] matrix, long mod = 0)
        {
            this.m_Matrix = matrix;
            Mod = mod;

            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    m_Matrix[i, j] %= mod;
                }
            }
        }

        public static MatrixInt GetIdentityMatrix(int size, long mod = 0)
        {
            long[,] matrix = new long[size,size];

            for (int i = 0; i < size; i++)
            {
                matrix[i, i] = 1;
            }

            return new MatrixInt(matrix, mod);
        }

        public long this[int i, int j]
        {
            get
            {
                return m_Matrix[i, j];
            }

            set
            {
                m_Matrix[i, j] = value;
            }
        }

        public static MatrixInt operator +(MatrixInt a, MatrixInt b)
        {
            int n = a.Size;
            long mod = Math.Max(a.Mod, b.Mod);
            long[,] c = new long[n,n];
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    c[i, j] = a[i, j] + b[i, j];
                }
            }

            if (mod > 0)
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        c[i, j] %= mod;
                    }
                }
            }

            return new MatrixInt(c, mod);
        }

        public static MatrixInt operator *(MatrixInt a, MatrixInt b)
        {
            int n = a.Size;
            long mod = Math.Max(a.Mod, b.Mod);

            long[,] c = new long[n,n];

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    for (int k = 0; k < n; k++)
                    {
                        c[i, j] += a[i, k] * b[k, j];
                        if (mod > 0)
                        {
                            c[i, j] %= mod;
                        }
                    }
                }
            }

            return new MatrixInt(c, mod);
        }
    }

    public static class Permutations
    {
        public static int[] GetRandomPermutation(int n)
        {
            int[] p = new int[n];
            for (int i = 0; i < n; i++)
            {
                p[i] = i;
            }

            Random random = new Random();
            for (int i = n - 1; i > 0; i--)
            {
                int j = random.Next(i + 1);
                int tmp = p[i];
                p[i] = p[j];
                p[j] = tmp;
            }

            return p;
        }

        public static T[] Shuffle<T>(this T[] array)
        {
            int length = array.Length;
            int[] p = GetRandomPermutation(length);
            T[] result = new T[length];
            for (int i = 0; i < length; i++)
            {
                result[i] = array[p[i]];
            }

            return result;
        }

        public static T[] ShuffleSort<T>(this T[] array)
        {
            var result = array.Shuffle();
            Array.Sort(result);
            return result;
        }
    }

    internal static class Algebra
    {
        public static long Phi(long n)
        {
            long result = n;
            for (long i = 2; i * i <= n; i++)
            {
                if (n % i == 0)
                {
                    while (n % i == 0)
                    {
                        n /= i;
                    }

                    result -= result / i;
                }
            }

            if (n > 1)
            {
                result -= result / n;
            }

            return result;
        }

        public static long BinPower(long a, long n, long mod)
        {
            long result = 1;

            while (n > 0)
            {
                if ((n & 1) != 0)
                {
                    result = (result * a) % mod;
                }

                a = (a * a) % mod;
                n >>= 1;
            }

            return result;
        }

        public static MatrixInt MatrixBinPower(MatrixInt a, long n)
        {
            MatrixInt result = MatrixInt.GetIdentityMatrix(a.Size, a.Mod);

            while (n > 0)
            {
                if ((n & 1) != 0)
                {
                    result *= a;
                }

                a *= a;
                n >>= 1;
            }

            return result;
        }

        public static long Gcd(long a, long b)
        {
            return b == 0 ? a : Gcd(b, a % b);
        }

        public static long ExtendedGcd(long a, long b, out long x, out long y)
        {
            if (b == 0)
            {
                x = 1;
                y = 0;
                return a;
            }

            long x1;
            long y1;
            long d = ExtendedGcd(b, a % b, out x1, out y1);
            x = y1;
            y = x1 - (a / b) * y1;
            return d;
        }

        public static long Lcm(long a, long b)
        {
            return (a / Gcd(a, b)) * b;
        }

        public static bool[] GetPrimes(int n)
        {
            n = Math.Max(n, 2);
            bool[] prime = new bool[n + 1];
            for (int i = 2; i <= n; i++)
            {
                prime[i] = true;
            }

            for (int i = 2; i * i <= n; i++)
            {
                if (prime[i])
                {
                    if ((long)i * i <= n)
                    {
                        for (int j = i * i; j <= n; j += i)
                        {
                            prime[j] = false;
                        }
                    }
                }
            }

            return prime;
        }

        public static long GetFibonacciNumber(long n, long mod = 0)
        {
            long[,] matrix = new long[,] { { 0, 1 }, { 1, 1 } };

            MatrixInt result = MatrixBinPower(new MatrixInt(matrix, mod), n);

            return result[1, 1];
        }

        public static long[] GetFibonacciSequence(int n)
        {
            long[] result = new long[n];
            result[0] = result[1] = 1;

            for (int i = 2; i < n; i++)
            {
                result[i] = result[i - 1] + result[i - 2];
            }

            return result;
        }

        public static long GetInverseElement(long a, long mod)
        {
            long x, y;
            long g = ExtendedGcd(a, mod, out x, out y);

            if (g != 1)
            {
                return -1;
            }

            return ((x % mod) + mod) % mod;
        }

        public static long[] GetAllInverseElements(long mod)
        {
            long[] result = new long[mod];
            result[1] = 1;
            for (int i = 2; i < mod; i++)
            {
                result[i] = (mod - (((mod / i) * result[mod % i]) % mod)) % mod;
            }

            return result;
        }

        public static int GetMinimalPrimeDivisor(int n)
        {
            for (int i = 2; i * i <= n; i++)
            {
                if (n % i == 0)
                {
                    return i;
                }
            }

            return n;
        }

        public static long Sqr(long x)
        {
            return x * x;
        }

        public static int SumOfDigits(long x, long baseMod = 10)
        {
            int res = 0;
            while (x > 0)
            {
                res += (int)(x % baseMod);
                x = x / baseMod;
            }
            return res;
        }
    }

    internal static class Reader
    {
        public static void ReadInt(out int a)
        {
            int[] number = new int[1];
            ReadInt(number);
            a = number[0];
        }

        public static void ReadInt(out int a, out int b)
        {
            int[] numbers = new int[2];
            ReadInt(numbers);
            a = numbers[0];
            b = numbers[1];
        }

        public static void ReadInt(out int int1, out int int2, out int int3)
        {
            int[] numbers = new int[3];
            ReadInt(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
        }

        public static void ReadInt(out int int1, out int int2, out int int3, out int int4)
        {
            int[] numbers = new int[4];
            ReadInt(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
            int4 = numbers[3];
        }

        public static void ReadLong(out long a)
        {
            long[] number = new long[1];
            ReadLong(number);
            a = number[0];
        }

        public static void ReadLong(out long a, out long b)
        {
            long[] numbers = new long[2];
            ReadLong(numbers);
            a = numbers[0];
            b = numbers[1];
        }

        public static void ReadLong(out long int1, out long int2, out long int3)
        {
            long[] numbers = new long[3];
            ReadLong(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
        }

        public static void ReadLong(out long int1, out long int2, out long int3, out long int4)
        {
            long[] numbers = new long[4];
            ReadLong(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
            int4 = numbers[3];
        }

        public static void ReadInt(int[] numbers)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            int count = Math.Min(numbers.Length, list.Length);

            for (int i = 0; i < count; i++)
            {
                numbers[i] = int.Parse(list[i]);
            }
        }

        public static int[] ReadDigits()
        {
            // ReSharper disable AssignNullToNotNullAttribute
            return Console.ReadLine().Select(x => int.Parse(x.ToString())).ToArray();
            // ReSharper restore AssignNullToNotNullAttribute
        }

        public static void ReadLong(long[] numbers)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            int count = Math.Min(numbers.Length, list.Length);

            for (int i = 0; i < count; i++)
            {
                numbers[i] = long.Parse(list[i]);
            }
        }

        public static void ReadDouble(double[] numbers)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            int count = Math.Min(numbers.Length, list.Length);

            for (int i = 0; i < count; i++)
            {
                numbers[i] = double.Parse(list[i]);
            }
        }

        public static void ReadDouble(out double a, out double b)
        {
            double[] numbers = new double[2];
            ReadDouble(numbers);
            a = numbers[0];
            b = numbers[1];
        }

        public static void ReadDouble(out double int1, out double int2, out double int3)
        {
            double[] numbers = new double[3];
            ReadDouble(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
        }

        public static string ReadLine()
        {
            return Console.ReadLine();
        }
    }

    public interface IGraph
    {
        int Vertices { get; set; }

        IList<int> this[int i] { get; }

        void AddEdge(int u, int v);

        void AddOrientedEdge(int u, int v);
    }

    public class Graph : IGraph
    {
        private readonly List<int>[] m_Edges;

        public int Vertices { get; set; }

        public IList<int> this[int i]
        {
            get
            {
                return this.m_Edges[i];
            }
        }

        public Graph(int vertices)
        {
            this.Vertices = vertices;

            this.m_Edges = new List<int>[vertices];

            for (int i = 0; i < vertices; i++)
            {
                this.m_Edges[i] = new List<int>();
            }
        }

        public void AddEdge(int u, int v)
        {
            this.AddOrientedEdge(u, v);
            this.AddOrientedEdge(v, u);
        }

        public void AddOrientedEdge(int first, int second)
        {
            this.m_Edges[first].Add(second);
        }

        public int[] Bfs(int start)
        {
            int[] d = new int[Vertices];
            for (int i = 0; i < Vertices; i++)
            {
                d[i] = -1;
            }

            Queue<int> queue = new Queue<int>();
            queue.Enqueue(start);
            d[start] = 0;

            while (queue.Count > 0)
            {
                int v = queue.Dequeue();
                foreach (int t in this.m_Edges[v].Where(t => d[t] == -1))
                {
                    queue.Enqueue(t);
                    d[t] = d[v] + 1;
                }
            }

            return d;
        }
    }

    internal class SimpleSumTable
    {
        private readonly int[,] m_Sum;

        public SimpleSumTable(int n, int m, int[,] table)
        {
            m_Sum = new int[n + 1,m + 1];

            for (int i = 1; i < n + 1; i++)
            {
                for (int j = 1; j < m + 1; j++)
                {
                    m_Sum[i, j] = m_Sum[i, j - 1] + m_Sum[i - 1, j] - m_Sum[i - 1, j - 1] + table[i - 1, j - 1];
                }
            }
        }

        public int GetSum(int l, int b, int r, int t)
        {
            return m_Sum[r + 1, t + 1] - m_Sum[r + 1, b] - m_Sum[l, t + 1] + m_Sum[l, b];
        }
    }

    internal class SegmentTreeSimpleInt<T>
    {
        public int Size { get; private set; }

        private readonly T[] m_Tree;

        private readonly Func<T, T, T> m_Operation;

        private readonly T m_Null;

        public SegmentTreeSimpleInt(int size, Func<T, T, T> operation, T nullElement, IList<T> array = null)
        {
            this.Size = size;
            this.m_Operation = operation;
            this.m_Null = nullElement;

            m_Tree = new T[4 * size];
            if (array != null)
            {
                this.Build(array, 1, 0, size - 1);
            }
        }

        private void Build(IList<T> array, int v, int tl, int tr)
        {
            if (tl == tr)
            {
                m_Tree[v] = array[tl];
            }
            else
            {
                int tm = (tl + tr) / 2;
                this.Build(array, 2 * v, tl, tm);
                this.Build(array, 2 * v + 1, tm + 1, tr);
                this.CalculateNode(v);
            }
        }

        public T GetSum(int l, int r)
        {
            return GetSum(1, 0, Size - 1, l, r);
        }

        private T GetSum(int v, int tl, int tr, int l, int r)
        {
            if (l > r)
            {
                return m_Null;
            }

            if (l == tl && r == tr)
            {
                return m_Tree[v];
            }

            int tm = (tl + tr) / 2;

            return this.m_Operation(
                GetSum(2 * v, tl, tm, l, Math.Min(r, tm)), GetSum(2 * v + 1, tm + 1, tr, Math.Max(l, tm + 1), r));
        }

        public void Update(int pos, T newValue)
        {
            Update(1, 0, Size - 1, pos, newValue);
        }

        private void Update(int v, int tl, int tr, int pos, T newValue)
        {
            if (tl == tr)
            {
                m_Tree[v] = newValue;
            }
            else
            {
                int tm = (tl + tr) / 2;
                if (pos <= tm)
                {
                    Update(2 * v, tl, tm, pos, newValue);
                }
                else
                {
                    Update(2 * v + 1, tm + 1, tr, pos, newValue);
                }
                this.CalculateNode(v);
            }
        }

        private void CalculateNode(int v)
        {
            m_Tree[v] = this.m_Operation(m_Tree[2 * v], m_Tree[2 * v + 1]);
        }
    }

    internal struct Pair<TFirst, TSecond>
    {
        public Pair(TFirst first, TSecond second)
            : this()
        {
            this.First = first;
            this.Second = second;
        }

        public TFirst First { set; get; }

        public TSecond Second { set; get; }
    }

    internal class FenwickTreeInt64
    {
        public FenwickTreeInt64(int size)
        {
            this.m_Size = size;
            m_Tree = new long[size];
        }

        public FenwickTreeInt64(int size, IList<long> tree)
            : this(size)
        {
            for (int i = 0; i < size; i++)
            {
                Inc(i, tree[i]);
            }
        }

        public long Sum(int r)
        {
            long res = 0;
            for (; r >= 0; r = (r & (r + 1)) - 1)
            {
                res += m_Tree[r];
            }
            return res;
        }

        public long Sum(int l, int r)
        {
            return Sum(r) - Sum(l - 1);
        }

        public void Inc(int i, long x)
        {
            for (; i < m_Size; i = i | (i + 1))
            {
                m_Tree[i] += x;
            }
        }

        public void Set(int i, long x)
        {
            Inc(i, x - Sum(i, i));
        }

        private readonly int m_Size;

        private readonly long[] m_Tree;
    }

    internal class AccumulativeDictionary<TKey> : Dictionary<TKey, int>
    {
        public new void Add(TKey key, int value = 1)
        {
            if (this.ContainsKey(key))
            {
                base[key] += value;
            }
            else
            {
                base.Add(key, value);
            }
        }

        public new int this[TKey key]
        {
            get
            {
                return this.ContainsKey(key) ? base[key] : 0;
            }
            set
            {
                this.Add(key, value);
            }
        }
    }

    internal class PriorityQueue<T>
    {
        public PriorityQueue(Comparison<T> comparison = null)
        {
            if (comparison == null)
            {
                if (typeof(T).GetInterfaces().Any(i => i == typeof(IComparable<T>)))
                {
                    m_Comparison = (a, b) => ((IComparable<T>)a).CompareTo(b);
                }
                else
                {
                    throw new ApplicationException("Add comparer");
                }
            }
            else
            {
                m_Comparison = comparison;
            }
        }

        public int Count { get; private set; }

        public void Enqueue(T item)
        {
            m_List.Add(item);
            m_Indexes.Add(item, this.Count);
            this.Count++;
            Up(this.Count);
        }

        public T Peek()
        {
            return m_List[0];
        }

        public T Dequeue()
        {
            if (this.Count > 0)
            {
                var result = m_List[0];

                Swap(0, this.Count - 1);
                m_Indexes.Remove(m_List[this.Count - 1]);
                m_List.RemoveAt(this.Count - 1);
                this.Count--;
                this.Down(1);

                return result;
            }
            throw new ApplicationException("Couldn't get element from empty queue");
        }

        public void Update(T item)
        {
            int index = m_Indexes[item];
            this.Up(index + 1);
        }

        private readonly List<T> m_List = new List<T>();

        private readonly Dictionary<T, int> m_Indexes = new Dictionary<T, int>();

        private readonly Comparison<T> m_Comparison;

        private void Up(int index)
        {
            while (index > 1 && m_Comparison.Invoke(m_List[index - 1], m_List[index / 2 - 1]) > 0)
            {
                this.Swap(index - 1, index / 2 - 1);

                index = index / 2;
            }
        }

        private void Down(int index)
        {
            while (2 * index <= this.Count && m_Comparison.Invoke(m_List[index - 1], m_List[2 * index - 1]) < 0
                   || 2 * index + 1 <= this.Count && m_Comparison.Invoke(m_List[index - 1], m_List[2 * index]) < 0)
            {
                if (2 * index + 1 > this.Count || m_Comparison.Invoke(m_List[2 * index - 1], m_List[2 * index]) > 0)
                {
                    this.Swap(index - 1, 2 * index - 1);
                    index = 2 * index;
                }
                else
                {
                    this.Swap(index - 1, 2 * index);
                    index = 2 * index + 1;
                }
            }
        }

        private void Swap(int i, int j)
        {
            var tmp = m_List[i];
            m_List[i] = m_List[j];
            m_List[j] = tmp;

            m_Indexes[m_List[i]] = i;
            m_Indexes[m_List[j]] = j;
        }
    }

    internal class HamiltonianPathFinder
    {
        public static void Run()
        {
            int n, m;
            Reader.ReadInt(out n, out m);
            List<int>[] a = new List<int>[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = new List<int>();
            }
            for (int i = 0; i < m; i++)
            {
                int x, y;
                Reader.ReadInt(out x, out y);
                a[x].Add(y);
                a[y].Add(x);
            }

            var rnd = new Random();

            bool[] v = new bool[n];
            int[] p = new int[n];
            for (int i = 0; i < n; i++)
            {
                p[i] = -1;
            }
            int first = rnd.Next(n);
            int cur = first;
            v[cur] = true;

            int count = 1;

            while (true)
            {
                var unb = a[cur].Where(u => !v[u]).ToList();
                int d = unb.Count;
                if (d > 0)
                {
                    int next = unb[rnd.Next(d)];
                    v[next] = true;
                    p[cur] = next;
                    cur = next;
                    count++;
                }
                else
                {
                    if (count  == n && a[cur].Contains(first))
                    {
                        p[cur] = first;
                        break;
                    }

                    d = a[cur].Count;
                    int pivot;
                    do
                    {
                        pivot = a[cur][rnd.Next(d)];
                    }
                    while (p[pivot] == cur);

                    int next = p[pivot];

                    int x = next;
                    int y = -1;
                    while (true)
                    {
                        int tmp = p[x];
                        p[x] = y;
                        y = x;
                        x = tmp;
                        if (y == cur)
                        {
                            break;
                        }
                    }
                    p[pivot] = cur;
                    cur = next;
                }
            }

            cur = first;
            do
            {
                Console.Write("{0} ", cur);
                cur = p[cur];
            }
            while (cur != first);
        }

        public static void WriteTest(int n)
        {
            Console.WriteLine("{0} {1}", 2 * n, 2 * (n - 1) + n);
            for (int i = 0; i < n - 1; i++)
            {
                Console.WriteLine("{0} {1}", 2 * i, 2 * i + 2);
                Console.WriteLine("{0} {1}", 2 * i + 1, 2 * i + 3);
                //Console.WriteLine("{0} {1}", 2 * i + 1, 2 * i + 2);
                //Console.WriteLine("{0} {1}", 2 * i, 2 * i + 3);
            }
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("{0} {1}", 2 * i, 2 * i + 1);
            }
        }
    }

    internal class Program
    {
        private static StreamReader m_InputStream;

        private static StreamWriter m_OutStream;

        private static void OpenFiles()
        {
            m_InputStream = new StreamReader("input.txt"); //File.OpenText("input.txt");
            Console.SetIn(m_InputStream);

            m_OutStream = new StreamWriter("output.txt"); //File.CreateText("output.txt");
            Console.SetOut(m_OutStream);
        }

        private static void CloseFiles()
        {
            m_OutStream.Flush();

            m_InputStream.Dispose();
            m_OutStream.Dispose();
        }

        private static void Main()
        {
            //OpenFiles();

            new Solution().Solve();

           // CloseFiles();
        }
    }

    internal class Solution
    {
        long[] a = new long[11];
        long[] p = new long[11];
        long[] r = new long[7];
        long[,] c = new long[11, 11];
        long mod = 1000000000 + 7;
        long[] p2 = new long[11];
        long[] p8 = new long[11];
        private int m;

        private long ans = 0;

        public void Solve()
        {
            for (int i = 0; i < 11; i++)
            {
                c[i, 0] = 1;
            }

            for (int i = 1; i < 11; i++)
            {
                for (int j = 1; j < 11; j++)
                {
                    c[i, j] = c[i - 1, j - 1] + c[i - 1, j];
                }
            }

            p2[0] = 1;
            p8[0] = 1;
            for (int i = 1; i < 11; i++)
            {
                p2[i] = 2 * p2[i - 1];
                p8[i] = 8 * p8[i - 1];
            }

            Reader.ReadInt(out m);
            p[1] = 1;
            for (int i = 2; i <= 10; i++)
            {
                p[i] = 10 * p[i - 1];
            }
            Go(10, 0, 0);
            a[0]--;

            CalcAns(0, 1);

            Console.WriteLine(ans);
        }

        private void CalcAns(int t, long count)
        {
            if (t > 0 && (r.Sum() - r[0] >= r[0]))
            {
                return;
            }

            if (t == 7)
            {
                if (r.Sum() - r[0] < r[0])
                {
                    ans = (ans + count)%mod;
                }
                return;
            }

            for (int i = 0; i < 10; i++)
            {
                if (a[i] > 0)
                {
                    r[t] = i;
                    long next = (count*a[i])%mod;
                    a[i]--;
                    CalcAns(t + 1, next);
                    a[i]++;
                    r[t] = 0;
                }
            }
        }

        private void Go(int t, int count, long current)
        {
            if (t == 0)
            {
                a[count]++;
                return;
            }

            for (int i = 0; i < 10; i++)
            {
                if (current + (i + 1) * p[t] <= m)
                {
                    int d = (i == 4 || i == 7) ? 1 : 0;
                    for (int j = 0; j < t; j++)
                    {
                        a[count + d + j] += c[t - 1, j]*p2[j]*p8[t - 1 - j];
                    }
                }
                else
                {
                    int d = (i == 4 || i == 7) ? 1 : 0;
                    Go(t - 1, count + d, current + i * p[t]);
                    break;
                }
            }
        }
    }
}


using System;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Linq;

namespace Codeforces.R316D1
{
    public struct ModInteger : IEquatable<ModInteger>
    {
        readonly int mod;
        readonly long value;
        public ModInteger(int mod, long value = 0L)
        {
            this.mod = mod;
            this.value = value % mod;
            if (value < 0)
            {
                this.value = value + mod;
            }
        }

        public bool Equals(ModInteger other)
        {
            return mod == other.mod && value == other.value;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is ModInteger))
            {
                return false;
            }
            var other = (ModInteger)obj;
            return Equals(other);
        }

        public override int GetHashCode()
        {
            return (int)value;
        }

        public static bool operator ==(ModInteger left, ModInteger right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(ModInteger left, ModInteger right)
        {
            return !(left == right);
        }

        public static ModInteger LeftShift(ModInteger left, int right)
        {
            return left << right;
        }

        public static ModInteger operator <<(ModInteger left, int right)
        {
            if (right > 32)
            {
                return left << 32 << (right - 32);
            }
            return new ModInteger(left.mod, left.value << right);
        }

        public static ModInteger Add(ModInteger left, int right)
        {
            return left + right;
        }

        public static ModInteger operator +(ModInteger left, int right)
        {
            return new ModInteger(left.mod, left.value + right);
        }

        public static ModInteger operator ++(ModInteger m)
        {
            return m + 1;
        }

        public static ModInteger Multiply(ModInteger left, int right)
        {
            return new ModInteger(left.mod, left.value * right);
        }

        public static ModInteger operator *(ModInteger left, int right)
        {
            return Multiply(left, right);
        }

        public static ModInteger Div(int left, int right, int mod)
        {
            return Pow(right, mod - 2, mod) * left;
        }

        public static ModInteger Pow(long x, int n, int mod)
        {
            var res = 1L;
            for (; n > 0; n >>= 1)
            {
                if ((n & 1) == 1)
                {
                    res = res * x % mod;
                }
                x = x * x % mod;
            }
            return new ModInteger(mod, res);
        }

        public static ModInteger ToModInteger(int value)
        {
            return new ModInteger(0, value);
        }

        public static implicit operator int(ModInteger value)
        {
            return (int)value.value;
        }

        public static int ToInt32(ModInteger value)
        {
            return value;
        }

        public static ModInteger Increment(ModInteger item)
        {
            return ++item;
        }
    }
    public static class Solver
    {
        const int mod = 1000000007;
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            Contract.Requires(tr != null);
            Contract.Requires(tw != null);

            tw.WriteLine(Parse(tr));
        }

        private static int Parse(TextReader tr)
        {
            var info = CultureInfo.InvariantCulture;
            tr.ReadLine();
            var a = tr.ReadLine().Split().Select(x => int.Parse(x, info)).ToArray();

            return Calc(a);
        }

        private static ModInteger Calc(int[] a)
        {
            int num1 = a.Count(x => x == 1);
            int num2 = a.Length - num1;

            return F(num1, num2);
        }

        private static ModInteger F(int a, int b)
        {
            var res = new ModInteger(mod, 1);

            for (int i = 0; i < b; ++i)
            {
                res *= a + 1 + i;
            }

            if (a == 0)
            {
                return res;
            }

            var I = new ModInteger[a + 1];
            I[0] = new ModInteger(mod, 1);
            I[1] = new ModInteger(mod, 1);
            for (int i = 2; i <= a; ++i)
            {
                I[i] = I[i - 1] + (i - 1) * I[i - 2];
            }
            return res * I[a];
        }
    }
}


using System;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Linq;

namespace Codeforces.R316D1
{
    public struct ModInteger : IEquatable<ModInteger>
    {
        readonly int mod;
        readonly long value;
        public ModInteger(int mod, long value = 0L)
        {
            this.mod = mod;
            this.value = value % mod;
            if (value < 0)
            {
                this.value = value + mod;
            }
        }

        public bool Equals(ModInteger other)
        {
            return mod == other.mod && value == other.value;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is ModInteger))
            {
                return false;
            }
            var other = (ModInteger)obj;
            return Equals(other);
        }

        public override int GetHashCode()
        {
            return (int)value;
        }

        public static bool operator ==(ModInteger left, ModInteger right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(ModInteger left, ModInteger right)
        {
            return !(left == right);
        }

        public static ModInteger LeftShift(ModInteger left, int right)
        {
            return left << right;
        }

        public static ModInteger operator <<(ModInteger left, int right)
        {
            if (right > 32)
            {
                return left << 32 << (right - 32);
            }
            return new ModInteger(left.mod, left.value << right);
        }

        public static ModInteger Add(ModInteger left, int right)
        {
            return left + right;
        }

        public static ModInteger operator +(ModInteger left, int right)
        {
            return new ModInteger(left.mod, left.value + right);
        }

        public static ModInteger operator ++(ModInteger m)
        {
            return m + 1;
        }

        public static ModInteger Multiply(ModInteger left, int right)
        {
            return new ModInteger(left.mod, left.value * right);
        }

        public static ModInteger operator *(ModInteger left, int right)
        {
            return Multiply(left, right);
        }

        public static ModInteger Div(int left, int right, int mod)
        {
            return Pow(right, mod - 2, mod) * left;
        }

        public static ModInteger Pow(long x, int n, int mod)
        {
            var res = 1L;
            for (; n > 0; n >>= 1)
            {
                if ((n & 1) == 1)
                {
                    res = res * x % mod;
                }
                x = x * x % mod;
            }
            return new ModInteger(mod, res);
        }

        public static ModInteger ToModInteger(int value)
        {
            return new ModInteger(0, value);
        }

        public static implicit operator int(ModInteger value)
        {
            return (int)value.value;
        }

        public static int ToInt32(ModInteger value)
        {
            return value;
        }

        public static ModInteger Increment(ModInteger item)
        {
            return ++item;
        }
    }
    public static class Solver
    {
        const int mod = 1000000007;
        public static void Main()
        {
            using (var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false })
            {
                Solve(Console.In, sw);
            }
        }

        public static void Solve(TextReader tr, TextWriter tw)
        {
            Contract.Requires(tr != null);
            Contract.Requires(tw != null);

            tw.WriteLine(Parse(tr));
        }

        private static int Parse(TextReader tr)
        {
            var info = CultureInfo.InvariantCulture;
            tr.ReadLine();
            var a = tr.ReadLine().Split().Select(x => int.Parse(x, info)).ToArray();

            return Calc(a);
        }

        private static ModInteger Calc(int[] a)
        {
            int num1 = a.Count(x => x == 1);
            int num2 = a.Length - num1;

            return F(num1, num2);
        }

        private static ModInteger F(int a, int b)
        {
            var res = new ModInteger(mod, 1);

            for (int i = 0; i < b; ++i)
            {
                res *= a + 1 + i;
            }

            var I = new ModInteger[a + 1];
            I[0] = new ModInteger(mod, 1);
            I[1] = new ModInteger(mod, 1);
            for (int i = 2; i <= a; ++i)
            {
                I[i] = I[i - 1] + (i - 1) * I[i - 2];
            }
            return res * I[a];
        }
    }
}


using System;
using System.IO;
using System.Linq;
using System.Text;

namespace Phone_Number
{
    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)
        {
            string s = reader.ReadLine();
            int[] nn = s.ToCharArray().Select(e => e - '0').ToArray();

            var dp = new long[10,nn.Length];
            for (int i = 0; i < 10; i++)
            {
                dp[i, 0] = 1;
            }

            for (int j = 1; j < nn.Length; j++)
            {
                for (int i = 0; i < 10; i++)
                {
                    int ss = i + nn[j];
                    if (ss%2 == 0)
                        dp[ss/2, j] += dp[i, j - 1];
                    else
                    {
                        dp[ss/2, j] += dp[i, j - 1];
                        dp[(ss + 1)/2, j] += dp[i, j - 1];
                    }
                }
            }

            long sum = -1;
            for (int i = 0; i < 10; i++)
            {
                sum += dp[i, nn.Length - 1];
            }
            for (int i = 1; i < nn.Length; i++)
            {
                if (Math.Abs(nn[i] - nn[i - 1]) > 1)
                {
                    sum++;
                    break;
                }
            }

            writer.WriteLine(sum);
            writer.Flush();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProgrammingContest.Codeforces.SchoolTeam2
{
    class H
    {
        public static void Main()
        {
            string s = Console.ReadLine();
            int n = s.Length;
            long[,] dp = new long[n, 10];

            long res = 0;
            bool self = false;
            for (int u = 0; u < 10; u++)
            {
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < 10; j++)
                        dp[i, j] = 0;
                dp[0, u] = 1;
                for (int i = 1; i < n; i++)
                {
                    int x = s[i] - '0';
                    for (int j = 0; j < 10; j++)
                    {
                        int y = j + x;
                        for (int k = 0; k <= y % 2; k++)
                            dp[i, y / 2 + k] += dp[i - 1, j];
                    }
                }
                for (int i = 0; i < 10; i++) res += dp[n - 1, i];

                bool b = true;
                for (int i = 0; i < n; i++) b &= dp[i, s[i] - '0'] > 0;
                self |= b;
            }

            Console.WriteLine(res - (self ? 1 : 0));
        }
    }
}


using System;
using System.Collections.Generic;

namespace AprilFoolsDayContest2021
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = int.Parse(Console.ReadLine());

            Console.WriteLine((2 + i) / 2);
        }

        static void CMain(string[] args)
        {
            string word = Console.ReadLine();

            for (int i = 1; i < word.Length - 1; i++)
            {
                if (((word[i - 1] - 65) + (word[i] - 65)) % 26 != (word[i + 1] - 65))
                {
                    Console.WriteLine("NO");
                    return;
                }
            }

            Console.WriteLine("YES");
        }

        static void XMain(string[] args)
        {
            int num = int.Parse(Console.ReadLine());

            double root = Math.Sqrt(num);
            int _root = (int)root;
            int proot = _root - 1;
            int nroot = _root + 1;

            if (root - proot > nroot - root)
            {
                if (root - _root > nroot - root)
                {
                    Console.WriteLine(nroot);
                } else
                {
                    Console.WriteLine(_root);
                }
            } else
            {
                if (root - _root > root - proot)
                {
                    Console.WriteLine(proot);
                }
                else
                {
                    Console.WriteLine(_root);
                }
            }
        }

        static void AMain(string[] args)
        {
            while (Console.In.Peek() != -1)
            {
                string test = Console.ReadLine();
                if (test.ToLower().Equals("Is it rated?".ToLower()))
                {
                    Console.WriteLine("No");
                } else
                {
                    Console.WriteLine("No");
                }
                Console.Out.Flush();
            }
        }
    }
}


using System;
using System.Collections.Generic;

namespace AprilFoolsDayContest2021
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = int.Parse(Console.ReadLine());

            Console.WriteLine((2 - i*i));
        }

        static void CMain(string[] args)
        {
            string word = Console.ReadLine();

            for (int i = 1; i < word.Length - 1; i++)
            {
                if (((word[i - 1] - 65) + (word[i] - 65)) % 26 != (word[i + 1] - 65))
                {
                    Console.WriteLine("NO");
                    return;
                }
            }

            Console.WriteLine("YES");
        }

        static void XMain(string[] args)
        {
            int num = int.Parse(Console.ReadLine());

            double root = Math.Sqrt(num);
            int _root = (int)root;
            int proot = _root - 1;
            int nroot = _root + 1;

            if (root - proot > nroot - root)
            {
                if (root - _root > nroot - root)
                {
                    Console.WriteLine(nroot);
                } else
                {
                    Console.WriteLine(_root);
                }
            } else
            {
                if (root - _root > root - proot)
                {
                    Console.WriteLine(proot);
                }
                else
                {
                    Console.WriteLine(_root);
                }
            }
        }

        static void AMain(string[] args)
        {
            while (Console.In.Peek() != -1)
            {
                string test = Console.ReadLine();
                if (test.ToLower().Equals("Is it rated?".ToLower()))
                {
                    Console.WriteLine("No");
                } else
                {
                    Console.WriteLine("No");
                }
                Console.Out.Flush();
            }
        }
    }
}


using System;
using System.Linq;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
using Number = System.Boolean;
namespace Program
{
    public class Solver
    {

        public void Solve()
        {
            var n = sc.Integer();
            var s = sc.Scan();
            var X = new List<int>();
            var Y = new List<int>();
            var Z = new List<int>();
            for (int i = 0; i < n; i++)
            {
                var c = s[i];
                if (c == 'V') { X.Add(i); }
                else if (c == 'K') { Y.Add(i); }
                else { Z.Add(i); }
            }
            var x = X.Count; var y = Y.Count; var z = Z.Count;
            X.Add(n + 1000000); Y.Add(n + 1000000); Z.Add(n + 1000000);
            var D = new List<int>[] { X, Y, Z };
            var dp = new int[x + 2, y + 2, 2];
            for (int i = 0; i < x + 2; i++)
                for (int j = 0; j < y + 2; j++)
                    for (int k = 0; k < 2; k++)
                        dp[i, j, k] = 1000000;
            dp[0, 0, 0] = 0;
            for (int pos = 0; pos < n; pos++)
            {
                var next = new int[x + 2, y + 2, 2];
                for (int i = 0; i < x + 2; i++)
                    for (int j = 0; j < y + 2; j++)
                        for (int k = 0; k < 2; k++)
                            next[i, j, k] = 1000000;
                for (int a = 0; a < x + 1; a++)
                    for (int b = 0; b < y + 1; b++)
                    {
                        var c = pos - a - b;
                        if (c < 0) continue;
                        if (c > z) continue;
                        var vec = new int[] { a, b, c };
                        for (int k = 0; k < 2; k++)
                        {
                            if (dp[a, b, k] >= 1000000) continue;
                            next[a + 1, b, 1] = Math.Min(next[a + 1, b, 1], dp[a, b, k] + d(X[a], 0, vec, D));
                            if (k != 1)
                                next[a, b + 1, 0] = Math.Min(next[a, b + 1, 0], dp[a, b, k] + d(Y[b], 1, vec, D));
                            next[a, b, 0] = Math.Min(next[a, b, 0], dp[a, b, k] + d(Z[c], 2, vec, D));
                        }
                    }
                dp = next;
            }
            IO.Printer.Out.WriteLine(Math.Min(dp[x, y, 0], dp[x, y, 1]));

        }
        int d(int p, int k, int[] P, List<int>[] D)
        {
            var v = 0;
            for (int i = 0; i < 3; i++)
            {
                if (i == k) continue;
                for (int j = 0; j < P[i]; j++)
                    if (p < D[i][j]) v++;
            }
            return v;
        }

        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }
    }
}

#region main
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Text;
    using System.Globalization;
    public class Printer: StreamWriter
    {
        static Printer() { Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false }; }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, T[] source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, T[] source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while ((b < 33 || 126 < b) && !isEof); return (char)b; }

        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n'; b = (char)read())
                if (b == 0) break;
                else if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != 0 && b != '-' && (b < '0' || '9' < b));
            if (b == 0) return long.MinValue;
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { var s = Scan(); return s != "" ? double.Parse(s, CultureInfo.InvariantCulture) : double.NaN; }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public char[] Char(int n) { return enumerate(n, Char); }
        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
    }
}
#endregion


using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
//using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

//using System.Threading;

namespace ReadWriteTemplate
{
    public static class Solver
    {
        private static void SolveCase()
        {
            /*Random random = new Random();
            for (int kk = 0; kk < 50; kk++)
            {
                for (int i = 0; i < 250; i++)
                {
                    Writer.Write("{0} ", random.Next(201));
                }
                Writer.WriteLine();
            }*/

            int[] a = ReadIntArray();
            int n = a.Length;
            int s = 10; // ???
            // double min = a.Min();
            // double max = a.Max();
            // double d = max - min;
            // min -= d / 2 / n;
            // max += d / 2 / n;

            double p = a.Average();
            //double sum = GetValue(a, s, n, a.Max());
            double mean = a.Average();
            double sum = a.Sum(x => (x - mean) * (x - mean));
            sum /= (a.Max() - a.Min()) * (a.Max() - a.Min());

            int k = s - 3;
            // double X = 2.17;
            double X = 40;

            maxx = Math.Min(maxx, sum);
            // Writer.WriteLine(maxx);
            bool isUniform = sum > 15;
            Writer.WriteLine(isUniform ? "uniform" : "poisson");
            if (isUniform)
            {
                //Writer.WriteLine((a.Min() + a.Max()) / 2);
            }
            else
            {
                //int R = 50;
                //a = a.OrderBy(x => x).Take(a.Length - R).Skip(R).ToArray();
                //Writer.WriteLine(((int)Math.Round(a.Average())));
            }
        }

        private static double GetValue(int[] a, int s, int n, double max)
        {
            double min = 0;
            double e = (max - min) / s;

            int[] count = new int[s];
            for (int i = 0; i < n; i++)
            {
                int index = (int)((a[i] - min - 1e-10) / e);
                if (index < 0)
                {
                    index = 0;
                }
                if (index >= s)
                {
                    index = s - 1;
                }
                count[index]++;
            }

            double np = (double)n / s;
            double sum = count.Sum(x => (x - np) * (x - np) / np);
            return sum;
        }

        public static double maxx = double.MaxValue;

        public static void Solve()
        {
            int T = ReadInt();
            for (int i = 0; i < T; i++)
            {
                //Writer.Write("Case #{0}: ", i + 1);
                SolveCase();
            }
        }

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

            public int X;

            public int Y;

            protected bool Equals(Point other)
            {
                return X == other.X && Y == other.Y;
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }
                if (ReferenceEquals(this, obj))
                {
                    return true;
                }
                if (obj.GetType() != this.GetType())
                {
                    return false;
                }
                return Equals((Point)obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    return (X * 397) ^ Y;
                }
            }
        }

        public static class Standard
        {
            public static long Power(long x, long p, long mod)
            {
                long result = 1;
                while (p > 0)
                {
                    if ((p & 1) == 0)
                    {
                        x = (x * x) % mod;
                        p >>= 1;
                    }
                    else
                    {
                        result = (result * x) % mod;
                        p--;
                    }
                }
                return result;
            }

            public static long Gcd(long a, long b)
            {
                return b == 0 ? a : Gcd(b, a % b);
            }

            public static List<int> GetPrimes(int n)
            {
                bool[] isPrime = Enumerable.Repeat(true, n).ToArray();
                isPrime[0] = false;
                isPrime[1] = false;
                for (int i = 2; i < n; i++)
                {
                    if (isPrime[i])
                    {
                        for (int j = i + i; j < n; j += i)
                        {
                            isPrime[j] = false;
                        }
                    }
                }
                List<int> primes = new List<int>();
                for (int i = 0; i < n; i++)
                {
                    if (isPrime[i])
                    {
                        primes.Add(i);
                    }
                }
                return primes;
            }
        }

        public static void Main()
        {
            //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

#if DEBUG
            //Reader = Console.In; Writer = Console.Out;
            Reader = File.OpenText("input.txt"); Writer = File.CreateText("output.txt");
#else
            Reader = Console.In; Writer = Console.Out;
#endif

            Solve();

            Reader.Close();
            Writer.Close();
        }

        public static IOrderedEnumerable<TSource> OrderByWithShuffle<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            return source.Shuffle().OrderBy(keySelector);
        }

        public static T[] Shuffle<T>(this IEnumerable<T> source)
        {
            T[] result = source.ToArray();
            Random rnd = new Random();
            for (int i = result.Length - 1; i >= 1; i--)
            {
                int k = rnd.Next(i + 1);
                T tmp = result[k];
                result[k] = result[i];
                result[i] = tmp;
            }
            return result;
        }

        #region Read/Write

        private static TextReader Reader;

        private static TextWriter Writer;

        private static Queue<string> CurrentLineTokens = new Queue<string>();

        private static string[] ReadAndSplitLine()
        {
            return Reader.ReadLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
        }

        public static string ReadToken()
        {
            while (CurrentLineTokens.Count == 0)
                CurrentLineTokens = new Queue<string>(ReadAndSplitLine());
            return CurrentLineTokens.Dequeue();
        }

        public static string ReadLine()
        {
            return Reader.ReadLine();
        }

        public static int ReadInt()
        {
            return int.Parse(ReadToken());
        }

        public static long ReadLong()
        {
            return long.Parse(ReadToken());
        }

        public static double ReadDouble()
        {
            return double.Parse(ReadToken(), CultureInfo.InvariantCulture);
        }

        public static int[] ReadIntArray()
        {
            return ReadAndSplitLine().Select(int.Parse).ToArray();
        }

        public static long[] ReadLongArray()
        {
            return ReadAndSplitLine().Select(long.Parse).ToArray();
        }

        public static double[] ReadDoubleArray()
        {
            return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray();
        }

        public static int[][] ReadIntMatrix(int numberOfRows)
        {
            int[][] matrix = new int[numberOfRows][];
            for (int i = 0; i < numberOfRows; i++)
                matrix[i] = ReadIntArray();
            return matrix;
        }

        public static string[] ReadLines(int quantity)
        {
            string[] lines = new string[quantity];
            for (int i = 0; i < quantity; i++)
                lines[i] = Reader.ReadLine().Trim();
            return lines;
        }

        public static void WriteArray<T>(IEnumerable<T> array)
        {
            Writer.WriteLine(string.Join(" ", array));
        }

        #endregion
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace TestProject
{
    class Program
    {
        static void Main(string[] args)
        {
            //read input
            var hw = Console.ReadLine().Split(' ');
            var h = int.Parse(hw[0]);
            var w = int.Parse(hw[1]);

            var field = new List<B>();
            for (var i = 0; i < h; i++)
            {
                var row = Console.ReadLine().ToCharArray();
                for (var j = 0; j < w; j++)
                {
                    if (row[j] == '*')
                    {
                        field.Add(new B { X = j, Y = i });
                    }
                }
            }

            var mouse = new B { Y = 0, X = 0 };
            var count = 0;
            //move mouse
            while (field.Any())
            {
                field = field.Where(b => b.X >= mouse.X && b.Y >= mouse.Y).ToList();
                if(!field.Any())
                {
                    break;
                }
                field = field.OrderBy(b => b.X - mouse.X + b.Y - mouse.Y).ToList();
                if (!field.Any())
                {
                    break;
                }
                mouse = field.First();
                field.RemoveAt(0);
                count++;
            }
            Console.WriteLine(count);
            Console.ReadLine();
        }

        class B
        {
            public int X { get; set; }
            public int Y { get; set; }
        }
    }
}


using System;
using System.Linq;
using CompLib.Mathematics;
using CompLib.Util;

public class Program
{
    long N, K;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextLong();
        K = sc.NextLong();

        // n*n盤面 にn個のルーク(飛車)を置く

        // すべての空のマスが攻撃を受ける
        // k個の互いに攻撃しあうペアがある
        // 何通りか?

        // 各行に1つづつある
        // i列目にc[i]個 ペアがc[i] -1個増える

        // j列に分ける ペアの数 n-j

        if (K >= N)
        {
            Console.WriteLine(0);
            return;
        }

        if (K == 0)
        {
            ModInt ans = 1;
            for (int i = 1; i <= N; i++)
            {
                ans *= i;
            }

            Console.WriteLine(ans);
            return;
        }

        // n個をn-k列に分ける方法
        long j = N - K;

        ModInt a = 1;
        ModInt b = 1;
        for (int i = 0; i < j; i++)
        {
            b *= i + 1;
            a *= N - i;
        }

        // 列の選び方 n C n-k
        ModInt[] fact = new ModInt[j+1];
        fact[0] = 1;
        for (int i = 1; i <= j; i++)
        {
            fact[i] = fact[i - 1] * i;
        }
        // 駒の振り分け方 j^n - (j-1)^n
        ModInt c = 0;
        for (int i = 0; i < j; i++)
        {
            // (j-i)^n * j C i
            c += ModInt.Pow(j - i, N) * fact[j] * ModInt.Inverse(fact[j - i] * fact[i]) * (i % 2 == 0 ? 1 : -1);
        }

        // Console.WriteLine(a * ModInt.Inverse(b));
        ModInt e = a * ModInt.Inverse(b) * c * 2;
        Console.WriteLine(e);
    }

    public static void Main(string[] args) => new Program().Solve();
}

// https://bitbucket.org/camypaper/complib
namespace CompLib.Mathematics
{
    #region ModInt
    /// <summary>
    /// [0,<see cref="Mod"/>) までの値を取るような数
    /// </summary>
    public struct ModInt
    {
        /// <summary>
        /// 剰余を取る値．
        /// </summary>
        public const long Mod = 998244353;

        /// <summary>
        /// 実際の数値．
        /// </summary>
        public long num;
        /// <summary>
        /// 値が <paramref name="n"/> であるようなインスタンスを構築します．
        /// </summary>
        /// <param name="n">インスタンスが持つ値</param>
        /// <remarks>パフォーマンスの問題上，コンストラクタ内では剰余を取りません．そのため，<paramref name="n"/> ∈ [0,<see cref="Mod"/>) を満たすような <paramref name="n"/> を渡してください．このコンストラクタは O(1) で実行されます．</remarks>
        public ModInt(long n) { num = n; }
        /// <summary>
        /// このインスタンスの数値を文字列に変換します．
        /// </summary>
        /// <returns>[0,<see cref="Mod"/>) の範囲内の整数を 10 進表記したもの．</returns>
        public override string ToString() { return num.ToString(); }
        public static ModInt operator +(ModInt l, ModInt r) { l.num += r.num; if (l.num >= Mod) l.num -= Mod; return l; }
        public static ModInt operator -(ModInt l, ModInt r) { l.num -= r.num; if (l.num < 0) l.num += Mod; return l; }
        public static ModInt operator *(ModInt l, ModInt r) { return new ModInt(l.num * r.num % Mod); }
        public static implicit operator ModInt(long n) { n %= Mod; if (n < 0) n += Mod; return new ModInt(n); }

        /// <summary>
        /// 与えられた 2 つの数値からべき剰余を計算します．
        /// </summary>
        /// <param name="v">べき乗の底</param>
        /// <param name="k">べき指数</param>
        /// <returns>繰り返し二乗法により O(N log N) で実行されます．</returns>
        public static ModInt Pow(ModInt v, long k) { return Pow(v.num, k); }

        /// <summary>
        /// 与えられた 2 つの数値からべき剰余を計算します．
        /// </summary>
        /// <param name="v">べき乗の底</param>
        /// <param name="k">べき指数</param>
        /// <returns>繰り返し二乗法により O(N log N) で実行されます．</returns>
        public static ModInt Pow(long v, long k)
        {
            long ret = 1;
            for (k %= Mod - 1; k > 0; k >>= 1, v = v * v % Mod)
                if ((k & 1) == 1) ret = ret * v % Mod;
            return new ModInt(ret);
        }
        /// <summary>
        /// 与えられた数の逆元を計算します．
        /// </summary>
        /// <param name="v">逆元を取る対象となる数</param>
        /// <returns>逆元となるような値</returns>
        /// <remarks>法が素数であることを仮定して，フェルマーの小定理に従って逆元を O(log N) で計算します．</remarks>
        public static ModInt Inverse(ModInt v) { return Pow(v, Mod - 2); }
    }
    #endregion
    #region Binomial Coefficient
    public class BinomialCoefficient
    {
        public ModInt[] fact, ifact;
        public BinomialCoefficient(int n)
        {
            fact = new ModInt[n + 1];
            ifact = new ModInt[n + 1];
            fact[0] = 1;
            for (int i = 1; i <= n; i++)
                fact[i] = fact[i - 1] * i;
            ifact[n] = ModInt.Inverse(fact[n]);
            for (int i = n - 1; i >= 0; i--)
                ifact[i] = ifact[i + 1] * (i + 1);
            ifact[0] = ifact[1];
        }
        public ModInt this[int n, int r]
        {
            get
            {
                if (n < 0 || n >= fact.Length || r < 0 || r > n) return 0;
                return fact[n] * ifact[n - r] * ifact[r];
            }
        }
        public ModInt RepeatedCombination(int n, int k)
        {
            if (k == 0) return 1;
            return this[n + k - 1, k];
        }
    }
    #endregion
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}