Problem:
Score : 500 points

Problem Statement

Given are N integers A_1,\ldots,A_N.

We will choose exactly K of these elements. Find the maximum possible product of the chosen elements.

Then, print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Constraints

1 \leq K \leq N \leq 2\times 10^5

|A_i| \leq 10^9

Input

Input is given from Standard Input in the following format:

N K
A_1 \ldots A_N

Output

Print the maximum product modulo (10^9+7), using an integer between 0 and 10^9+6 (inclusive).

Sample Input 1

4 2
1 2 -3 -4

Sample Output 1

12

The possible products of the two chosen elements are 2, -3, -4, -6, -8, and 12, so the maximum product is 12.

Sample Input 2

4 3
-1 -2 -3 -4

Sample Output 2

1000000001

The possible products of the three chosen elements are -24, -12, -8, and -6, so the maximum product is -6.

We print this value modulo (10^9+7), that is, 1000000001.

Sample Input 3

2 1
-1 1000000000

Sample Output 3

1000000000

The possible products of the one chosen element are -1 and 1000000000, so the maximum product is 1000000000.

Sample Input 4

10 10
1000000000 100000000 10000000 1000000 100000 10000 1000 100 10 1

Sample Output 4

999983200

Be sure to print the product modulo (10^9+7).

Solution in C# (Mono-csc 3.5.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using static System.Console;
using static System.Math;

namespace Atcoder
{
    class Program
    {
        static StreamWriter sw = new StreamWriter(OpenStandardOutput()) { AutoFlush = false };
        static void Main(string[] args)
        {
            try
            {
                SetOut(sw);
                Solve.Answer();
                Out.Flush();
            }
            catch (Exception ex)
            {
                WriteLine(ex.ToString());
            }
        }
    }

    public class Solve
    {
        public static void Answer()
        {
            var NK = IO.RSInt;
            var N = NK[0];
            var K = NK[1];
            var A = IO.RSInt;
            Array.Sort(A);
            Array.Reverse(A);
            var minus_A = new List<int>();
            var puls_A = new List<int>();
            for (int i = 0; i < A.Length; i++)
            {
                if (A[i] < 0) minus_A.Add(-A[i]);
                else puls_A.Add(A[i]);
            }

            long ans = 1;

            // 負になる場合
            if (K % 2 == 1 && minus_A.Count > K)
            {
                if (minus_A.Contains(0))
                    WriteLine(0);
                else
                {
                    minus_A.Sort();
                    for (int i = 0; i < K; i++)
                    {
                        ans = Mod.Multi(ans, -minus_A[i]);
                    }
                    WriteLine(ans + 1000000007);
                }
                return;
            }

            // 正になる場合
            minus_A.Sort();
            minus_A.Reverse();
            int mi = minus_A.Count();
            puls_A.Sort();
            puls_A.Reverse();
            var minus_cnt = 0;
            for (int i = 0; i < K; i++)
            {
                var minus = 0;
                if (minus_A.Count > 0)
                {
                    minus = minus_A.First();
                }
                else
                {
                    minus = -1;
                }
                var puls = 0;
                if (puls_A.Count > 0)
                {
                    puls = puls_A.First();
                }
                else
                {
                    puls = -1;
                }
                if (minus == -1 && puls == -1)
                    break;

                bool isMinusOK = true;
                if (mi % 2 == 1 && (minus_A.Count == 1 || i == K - 1))
                    isMinusOK = false;

                if (minus > puls && isMinusOK)
                {
                    if (minus == 0) break;
                    minus_A.RemoveAt(0);
                    ans = Mod.Multi(ans, minus);
                    minus_cnt++;
                }
                else
                {
                    if (puls == 0) break;
                    puls_A.RemoveAt(0);
                    ans = Mod.Multi(ans, puls);
                }
            }
            WriteLine(ans);
        }
    }

    class PriorityQueue<T>
  where T : IComparable<T>
    {
        #region フィールド

        List<T> buffer;

        #endregion
        #region 初期化

        public PriorityQueue() { this.buffer = new List<T>(); }
        public PriorityQueue(int capacity) { this.buffer = new List<T>(capacity); }

        #endregion
        #region ヒープ操作

        /// <summary>
        /// ヒープ化されている配列リストに新しい要素を追加する。
        /// </summary>
        /// <param name="array">対象の配列リスト</param>
        static void PushHeap(List<T> array, T elem)
        {
            int n = array.Count;
            array.Add(elem);

            while (n != 0)
            {
                int i = (n - 1) / 2;
                if (array[n].CompareTo(array[i]) > 0)
                {
                    T tmp = array[n]; array[n] = array[i]; array[i] = tmp;
                }
                n = i;
            }
        }

        /// <summary>
        /// ヒープから最大値を削除する。
        /// </summary>
        /// <param name="array">対象の配列リスト</param>
        static void PopHeap(List<T> array)
        {
            int n = array.Count - 1;
            array[0] = array[n];
            array.RemoveAt(array.Count - 1);

            for (int i = 0, j; (j = 2 * i + 1) < n;)
            {
                if ((j != n - 1) && (array[j].CompareTo(array[j + 1]) < 0))
                    j++;
                if (array[i].CompareTo(array[j]) < 0)
                {
                    T tmp = array[j]; array[j] = array[i]; array[i] = tmp;
                }
                i = j;
            }
        }

        #endregion
        #region 要素の挿入・削除

        /// <summary>
        /// 要素のプッシュ。
        /// </summary>
        /// <param name="elem">挿入したい要素</param>
        public void Push(T elem)
        {
            PushHeap(this.buffer, elem);
        }

        /// <summary>
        /// 要素を1つポップ。
        /// </summary>
        /// <remarks>
        /// 今回の実装では、先頭要素の読み出しと削除は別に行う。
        /// この Pop では削除のみ。
        /// 読み出しには Top プロパティを使う。
        /// </remarks>
        public void Pop()
        {
            PopHeap(this.buffer);
        }

        /// <summary>
        /// 先頭要素の読み出し。
        /// </summary>
        public T Top
        {
            get { return this.buffer[0]; }
        }

        public int Count
        {
            get { return this.buffer.Count; }
        }

        #endregion
    }

    public class IO
    {
        #region Input
        public static int RInt => int.Parse(ReadLine());
        public static long RLong => long.Parse(ReadLine());
        public static double RDouble => double.Parse(ReadLine());

        public static string[] RSString => ReadLine().Split();
        public static int[] RSInt => ReadLine().Split().Select(s => int.Parse(s)).ToArray();
        public static long[] RSLong => ReadLine().Split().Select(s => long.Parse(s)).ToArray();
        public static double[] RSDouble => ReadLine().Split().Select(s => double.Parse(s)).ToArray();
        #endregion

        #region Output
        public static void OutJoinSpace<T>(IEnumerable<T> list) => WriteLine(string.Join(" ", list));
        public static void WriteLineYes_or_No(bool flag) => WriteLine(flag ? "Yes" : "No");
        public static void WriteLineYES_or_NO(bool flag) => WriteLine(flag ? "YES" : "NO");
        #endregion
    }

    public class Mod
    {
        #region
        private readonly static long M = 1000000007;

        public static long Add(long a, long b) => (a * b) % M;
        public static long Sub(long a, long b) => (a - b) % M >= 0 ? (a - b) % M : (a - b) % M + M;
        public static long Multi(long a, long b) => (a * b) % M;
        #endregion
    }
}