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 Java8 (OpenJDK 1.8.0) (judge verdict: Runtime Error)

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author silviase
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        EHandshake solver = new EHandshake();
        solver.solve(1, in, out);
        out.close();
    }

    static class EHandshake {
        public void solve(int testNumber, Scanner in, PrintWriter out) {

            int n = in.nextInt();
            int m = in.nextInt();
            int[] f = new int[100001];
            for (int i = 0; i < n; i++) {
                f[in.nextInt()]++;
            }

            double[][] res = Arith.convolve(f, f);
            long happiness = 0;
            int idx = res[0].length - 1;

            while (m > 0) {
                long cnt = Math.min(Math.round(res[0][idx]), m);
                happiness += cnt * idx;
                m -= cnt;
                idx--;
            }
            out.println(happiness);

        }

    }

    static class Arith {
        public static double[][] convolve(int[] a, int[] b) {
            // 次数上界がna(>0)である多項式A(x)の係数ベクトルをa[]、
            // 次数上界がnb(>0)である多項式B(x)の係数ベクトルをb[]とした時に、
            // A(x)とB(x)の乗算の結果である多項式C(x)の係数ベクトルを戻り値として返す。
            // C(x)の次数上界はna+nb-1。
            // a, bの配列は変更しない
            // 複素演算を用いたFFT。(再帰なし。アルゴリズムイントロダクション30.3参照)
            int na = a.length;
            int nb = b.length;
            int m = Math.max(na, nb);
            int n = Integer.highestOneBit(2 * m - 1) << 1;

            double[][] ca = new double[2][n];
            double[][] cb = new double[2][n];
            for (int i = 0; i < na; i++) {
                ca[0][i] = a[i];
            }
            for (int i = 0; i < nb; i++) {
                cb[0][i] = b[i];
            }

            ca = FFT(ca, false);
            cb = FFT(cb, false);

            for (int i = 0; i < n; i++) {
//			ca[i] = ca[i].multiply(cb[i]);
                double rtmp = ca[0][i] * cb[0][i] - ca[1][i] * cb[1][i];
                double itmp = ca[0][i] * cb[1][i] + ca[1][i] * cb[0][i];
                ca[0][i] = rtmp;
                ca[1][i] = itmp;
            }

//		Complex[] ret = Arrays.copyOf(FFT(ca, true), na + nb - 1);
            double[][] ret = FFT(ca, true);
            ret[0] = Arrays.copyOf(ret[0], na + nb - 1);
            ret[1] = Arrays.copyOf(ret[1], na + nb - 1);
            for (int i = 0; i < na + nb - 1; i++) {
                ret[0][i] /= n;
                ret[1][i] /= n;
            }

            return ret;
        }

        private static double[][] FFT(double[][] a, boolean inverse) {
            // 複素数の係数ベクトルaを持つ多項式を、
            // 1の原始n乗根のべき乗の点で評価(evaluation)する
            // inverseがtrueの時は、補間(interporation)になる。(1/nはしない)
            // aの内容は戻り値に変更される。
            int n = a[0].length;

//		Complex[] ret = new Complex[n];
            double[][] ret = a;
//		double[][] ret = new double[2][n];
            for (int k = 0; k < n; k++) {
                int rev = Integer.reverse(k);
                rev >>>= Integer.numberOfLeadingZeros(n) + 1;

                if (k < rev) {
                    double tmp = ret[0][k];
                    ret[0][k] = ret[0][rev];
                    ret[0][rev] = tmp;
                    tmp = ret[1][k];
                    ret[1][k] = ret[1][rev];
                    ret[1][rev] = tmp;
                }
//			ret[0][rev] = a[0][k];
//			ret[1][rev] = a[1][k];
            }

            for (int m = 2; m <= n; m *= 2) {
                double th = 2 * Math.PI / m;
                double[] wn = {Math.cos(th), Math.sin(th)};
                if (inverse) {
                    wn[1] = -wn[1];
                }

                for (int k = 0; k < n; k += m) {
//				Complex w = new Complex(1, 0);
                    double[] w = new double[2];
                    w[0] = 1;

//				Complex t = new Complex(0, 0);
                    double[] t = new double[2];
                    for (int j = 0; j < m / 2; j++) {
//					Complex t = w.multiply(ret[k + j + m / 2]);
                        double tmp0 = ret[0][k + j + m / 2];
                        double tmp1 = ret[1][k + j + m / 2];
                        t[0] = w[0] * tmp0 - w[1] * tmp1;
                        t[1] = w[0] * tmp1 + w[1] * tmp0;
                        ret[0][k + j + m / 2] = ret[0][k + j] - t[0];
                        ret[1][k + j + m / 2] = ret[1][k + j] - t[1];
                        ret[0][k + j] = ret[0][k + j] + t[0];
                        ret[1][k + j] = ret[1][k + j] + t[1];

//					w = w.multiply(wn);
                        double rtmp = w[0] * wn[0] - w[1] * wn[1];
                        double itmp = w[0] * wn[1] + w[1] * wn[0];
                        w[0] = rtmp;
                        w[1] = itmp;
                    }
                }
            }

            return ret;
        }

    }
}