Problem:
Score : 500 points

Problem Statement

Takahashi has come to a party as a special guest.
There are N ordinary guests at the party. The i-th ordinary guest has a power of A_i.

Takahashi has decided to perform M handshakes to increase the happiness of the party (let the current happiness be 0).
A handshake will be performed as follows:

Takahashi chooses one (ordinary) guest x for his left hand and another guest y for his right hand (x and y can be the same).

Then, he shakes the left hand of Guest x and the right hand of Guest y simultaneously to increase the happiness by A_x+A_y.

However, Takahashi should not perform the same handshake more than once. Formally, the following condition must hold:

Assume that, in the k-th handshake, Takahashi shakes the left hand of Guest x_k and the right hand of Guest y_k. Then, there is no pair p, q (1 \leq p < q \leq M) such that (x_p,y_p)=(x_q,y_q).

What is the maximum possible happiness after M handshakes?

Constraints

1 \leq N \leq 10^5

1 \leq M \leq N^2

1 \leq A_i \leq 10^5

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
A_1 A_2 ... A_N

Output

Print the maximum possible happiness after M handshakes.

Sample Input 1

5 3
10 14 19 34 33

Sample Output 1

202

Let us say that Takahashi performs the following handshakes:

In the first handshake, Takahashi shakes the left hand of Guest 4 and the right hand of Guest 4.

In the second handshake, Takahashi shakes the left hand of Guest 4 and the right hand of Guest 5.

In the third handshake, Takahashi shakes the left hand of Guest 5 and the right hand of Guest 4.

Then, we will have the happiness of (34+34)+(34+33)+(33+34)=202.

We cannot achieve the happiness of 203 or greater, so the answer is 202.

Sample Input 2

9 14
1 3 5 110 24 21 34 5 3

Sample Output 2

1837

Sample Input 3

9 73
67597 52981 5828 66249 75177 64141 40773 79105 16076

Sample Output 3

8128170

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Linq;
using CompLib.Algorithm;

public class Program
{
    private int N;
    private long M;
    private int[] A;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        M = sc.NextLong();
        A = sc.IntArray();

        int max = -1;
        foreach (int i in A)
        {
            max = Math.Max(max, i);
        }

        long[] g = new long[max + 1];
        for (int i = 0; i < N; i++)
        {
            g[A[i]]++;
        }

        var cnt = FastFourierTransform.Convolution(g, g);
        long ans = 0;
        long sum = 0;
        for (int i = max + max; i >= 0; i--)
        {
            long t = sum + cnt[i];
            if (t > M)
            {
                long n = M - sum;
                ans += i * n;
                break;
            }

            ans += i * cnt[i];
            sum = t;
        }
        
        Console.WriteLine(ans);
    }


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

namespace CompLib.Algorithm
{
    using System;
    using System.Numerics;

    public static class FastFourierTransform
    {
        // private const int E = 50;
        // private const long N = 1L << E;
        //
        // // 1の原始N乗根
        // private const long O = 1521;
        // private const long InvO = 546857209190701451;
        //
        // private const long Mod = 1012 * N + 1;

        private const int E = 27;
        private const long N = 1L << E;
        private const long O = 137;
        private const long InvO = 749463956;
        private const long Mod = 15 * N + 1;


        // Z[i] 1の原始2^i乗根
        public static readonly ModInt[] Z;
        public static readonly ModInt[] InvZ;

        static FastFourierTransform()
        {
            Z = new ModInt[E + 1];
            InvZ = new ModInt[E + 1];
            Z[E] = O; // ZE☆
            InvZ[E] = InvO;
            for (int i = E - 1; i >= 0; i--)
            {
                Z[i] = Z[i + 1] * Z[i + 1];
                InvZ[i] = InvZ[i + 1] * InvZ[i + 1];
            }
        }

        /// <summary>
        /// a,bからc[k]=Σ(a[i]*b[k-i])を求める
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static long[] Convolution(long[] a, long[] b)
        {
            int len = 1;
            int l = 0;
            while (len < (a.Length + b.Length))
            {
                l++;
                len *= 2;
            }

            var mA = new ModInt[len];
            for (int i = 0; i < a.Length; i++)
            {
                mA[i] = a[i];
            }

            var mB = new ModInt[len];
            for (int i = 0; i < b.Length; i++)
            {
                mB[i] = b[i];
            }

            ModInt[] hatG = Transform(mA, l, false);
            ModInt[] hatH = Transform(mB, l, false);
            ModInt[] hatF = new ModInt[len];
            for (int i = 0; i < len; i++)
            {
                hatF[i] = hatG[i] * hatH[i];
            }

            ModInt[] nF = Transform(hatF, l, true);

            ModInt invLen = ModInt.Pow(len, Mod - 2);
            long[] f = new long[len];
            for (int i = 0; i < len; i++)
            {
                f[i] = (nF[i] * invLen)._num;
            }

            return f;
        }

        private static ModInt[] Transform(ModInt[] a, int l, bool inverse)
        {
            int len = 1 << l;
            if (len == 1)
            {
                return a;
            }

            ModInt[] a0 = new ModInt[len / 2];
            ModInt[] a1 = new ModInt[len / 2];

            for (int i = 0; i < len / 2; i++)
            {
                a0[i] = a[i * 2];
                a1[i] = a[i * 2 + 1];
            }

            ModInt[] hatF0 = Transform(a0, l - 1, inverse);
            ModInt[] hatF1 = Transform(a1, l - 1, inverse);

            ModInt zetaN = inverse ? InvZ[l] : Z[l];

            ModInt[] result = new ModInt[len];
            ModInt zetaNi = 1;
            for (int i = 0; i < len; i++)
            {
                result[i] = hatF0[i % (len / 2)] + zetaNi * hatF1[i % (len / 2)];
                zetaNi *= zetaN;
            }

            return result;
        }

        /// <summary>
        /// a,bからc[k]=Σ(a[i]*b[k-i])を求める
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static double[] Convolution(double[] a, double[] b)
        {
            int n = 1;
            while (n < (a.Length + b.Length))
            {
                n *= 2;
            }

            var compA = new Complex[n];
            for (int i = 0; i < a.Length; i++)
            {
                compA[i] = new Complex(a[i], 0);
            }

            var compB = new Complex[n];
            for (int i = 0; i < b.Length; i++)
            {
                compB[i] = new Complex(b[i], 0);
            }

            Complex[] hatG = Transform(compA);
            Complex[] hatH = Transform(compB);
            Complex[] hatF = new Complex[n];
            for (int i = 0; i < n; i++)
            {
                hatF[i] = hatG[i] * hatH[i];
            }

            Complex[] nF = Transform(hatF, true);

            double[] f = new double[n];
            for (int i = 0; i < n; i++)
            {
                f[i] = nF[i].Real / n;
            }

            return f;
        }

        public static Complex[] DiscreteFourierTransform(Complex[] a, bool inverse = false)
        {
            int n = 1;
            while (n < a.Length)
            {
                n *= 2;
            }

            Complex[] aa = new Complex[n];
            for (int i = 0; i < a.Length; i++)
            {
                aa[i] = a[i];
            }

            return Transform(aa, inverse);
        }

        // f(x) = Σa_i*x^i の離散フーリエ変換
        // deg(f)は2羃
        private static Complex[] Transform(Complex[] a, bool inverse = false)
        {
            int n = a.Length;
            if (n == 1)
            {
                return a;
            }

            Complex[] a0 = new Complex[n / 2];
            Complex[] a1 = new Complex[n / 2];
            for (int i = 0; i < n / 2; i++)
            {
                a0[i] = a[2 * i];
                a1[i] = a[2 * i + 1];
            }

            Complex[] hatF0 = Transform(a0, inverse);
            Complex[] hatF1 = Transform(a1, inverse);

            // ζ_n
            Complex zetaN = Zeta(inverse ? -n : n);

            var result = new Complex[n];

            // ζ_n^i
            Complex zetaNi = 1;
            for (int i = 0; i < n; i++)
            {
                result[i] = hatF0[i % (n / 2)] + zetaNi * hatF1[i % (n / 2)];
                zetaNi *= zetaN;
            }

            return result;
        }

        private static Complex Zeta(int n)
        {
            double rad = 2 * Math.PI / n;
            double re = Math.Cos(rad);
            double im = Math.Sin(rad);
            return new Complex(re, im);
        }

        public struct ModInt
        {
            public long _num { get; private set; }

            public ModInt(long n)
            {
                _num = n % Mod;
            }

            public static implicit operator ModInt(long n)
            {
                return new ModInt(n);
            }

            public static ModInt operator *(ModInt a, ModInt b)
            {
                if (Mod < int.MaxValue)
                {
                    return (a._num * b._num) % Mod;
                }

                long bb = b._num;
                ModInt result = 0;
                while (bb > 0)
                {
                    if (bb % 2 == 1)
                    {
                        result += a;
                    }

                    a += a;
                    bb /= 2;
                }

                return result;
            }

            public static ModInt operator +(ModInt a, ModInt b)
            {
                return (a._num + b._num) % Mod;
            }

            // a^(2^b)
            public static ModInt Pow2(ModInt a, int b)
            {
                ModInt result = a;
                for (int i = 0; i < b; i++)
                {
                    result *= result;
                }

                return result;
            }

            public static ModInt Pow(ModInt a, long b)
            {
                ModInt result = 1;
                while (b > 0)
                {
                    if (b % 2 == 1)
                    {
                        result *= a;
                    }

                    a *= a;
                    b /= 2;
                }

                return result;
            }
        }
    }
}

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

    const char Separator = ' ';
    private int _pos;
    private string[] _line;

    #region スペース区切りで取得

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

        return _line[_pos++];
    }

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }

    #endregion

    #region 型変換

    private int[] ToIntArray(string[] array)
    {
        var result = new int[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = int.Parse(array[i]);
        }

        return result;
    }

    private long[] ToLongArray(string[] array)
    {
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = long.Parse(array[i]);
        }

        return result;
    }

    private double[] ToDoubleArray(string[] array)
    {
        var result = new double[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = double.Parse(array[i]);
        }

        return result;
    }

    #endregion

    #region 配列取得

    public string[] Array()
    {
        if (_pos >= _line.Length)
            _line = Console.ReadLine().Split(Separator);

        _pos = _line.Length;
        return _line;
    }

    public int[] IntArray()
    {
        return ToIntArray(Array());
    }

    public long[] LongArray()
    {
        return ToLongArray(Array());
    }

    public double[] DoubleArray()
    {
        return ToDoubleArray(Array());
    }

    #endregion
}