Problem:
Score : 300 points

Problem Statement

We have a sequence of N integers A~=~A_0,~A_1,~...,~A_{N - 1}.

Let B be a sequence of K \times N integers obtained by concatenating K copies of A. For example, if A~=~1,~3,~2 and K~=~2, B~=~1,~3,~2,~1,~3,~2.

Find the inversion number of B, modulo 10^9 + 7.

Here the inversion number of B is defined as the number of ordered pairs of integers (i,~j)~(0 \leq i < j \leq K \times N - 1) such that B_i > B_j.

Constraints

All values in input are integers.

1 \leq N \leq 2000

1 \leq K \leq 10^9

1 \leq A_i \leq 2000

Input

Input is given from Standard Input in the following format:

N K
A_0 A_1 ... A_{N - 1}

Output

Print the inversion number of B, modulo 10^9 + 7.

Sample Input 1

2 2
2 1

Sample Output 1

3

In this case, B~=~2,~1,~2,~1. We have:

B_0 > B_1

B_0 > B_3

B_2 > B_3

Thus, the inversion number of B is 3.

Sample Input 2

3 5
1 1 1

Sample Output 2

0

A may contain multiple occurrences of the same number.

Sample Input 3

10 998244353
10 9 8 7 5 6 3 4 2 1

Sample Output 3

185297239

Be sure to print the output modulo 10^9 + 7.

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

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
	static void Main()
	{
    long mod = 1000000007;
    long answer = 0;
		string[] input = Console.ReadLine().Split(' ');
		int n = int.Parse(input[0]);
		long k = long.Parse(input[1]);
		long[] nums = Array.ConvertAll(Console.ReadLine().Split(' '),long.Parse);
    long x = FallCount(nums);
    //Console.WriteLine(x);
    x %= mod;
    
    Array.Sort(nums);
    long y = 0;
    long minCount = 0;
    for(int i = 1; i < n; i++)
    {
      if(nums[i] > nums[i-1])
      {
        minCount = i;
      }
      y += minCount;
      y %= mod;
    }
    
    answer = k*x;
    answer %= mod;
    
    long answerSub = (k-1)*k/2;
    answerSub %= mod;
    answerSub *= y;
    answerSub %= mod;

    answer += answerSub;
    answer %= mod;

		Console.WriteLine(answer);
	}

  static long FallCount(long[] nums)
  {//転倒数をO(nlogn)で求める。同じ数は転倒していないとする。
    long answer = 0;
    int n = nums.Length;
    long[,] numss = new long[n,2];
    for(int i = 0; i < n; i++)
    {
      numss[i,0] = nums[i];
      numss[i,1] = i;
    }
    long[,] numsCompress = CoordinateCompression(numss);
    long[] bits = new long[n+1];

    for(int i = 0; i < n; i++)
    {
      answer += BitSum(bits,n) - BitSum(bits,numsCompress[i,2]+1);
      bits = BitAdd(bits,numsCompress[i,2]+1,1);
    }

    return answer;
  }

  static long[] BitAdd(long[] bits, long i, long x)//BITでiだけにx加算。O(logn)
  {
    int n = bits.Length-1;
    while(i <= n)
    {
      bits[i] += x;
      i += i&-i;
    }
    return bits;
  }

  static long BitSum(long[] bits, long i)//BITでi以下の総和を計算。O(logn)
  {
    long sum = 0;
    while(i > 0)
    {
      sum += bits[i];
      i -= i&-i;
    }
    return sum;
  }

  static long[,] CoordinateCompression(long[,] vertexesOriginal)
    //1次元の座標圧縮をO(n)で行う。配列は0-indexで[x,順番]。compressedXも更新。
    //例えば、{2,4,4,3}は{0,2,2,1}を返す。
  {
    long n = vertexesOriginal.GetLength(0);//多次元配列の長さの取得
    long xCount = 1;//圧縮後のxの個数
    long[] compressedXmemo = new long[n];
    long[][] vertexes = new long[n][];
    for(long i = 0; i < n; i++)
    {
      vertexes[i] = new long[3];
      for(long j = 0; j < 2; j++)
      {
        vertexes[i][j] = vertexesOriginal[i,j];//配列をジャグ配列に置換
      }
    }

    Array.Sort(vertexes, (a, b) => a[0].CompareTo(b[0]));//x座標でソート
    vertexes[0][2] = 0;
    compressedXmemo[0] = vertexes[0][0];
    for(long i = 1; i < n; i++)
    {
      if(vertexes[i][0] == vertexes[i-1][0])//x座標が同じ
      {
        vertexes[i][2] = xCount - 1;
      }else
      {
        xCount++;
        vertexes[i][2] = xCount - 1;
        compressedXmemo[xCount-1] = vertexes[i][0];
      }
    }
    long[] compressedX = new long[xCount];
    for(long i = 0; i < xCount; i++) compressedX[i] = compressedXmemo[i];

    Array.Sort(vertexes, (a, b) => a[1].CompareTo(b[1]));//もとの番号順でソート

    long[,] answer = new long[n,3];
    for(long i = 0; i < n; i++)
    {
      for(long j = 0; j < 3; j++)
      {
        answer[i,j] = vertexes[i][j];//ジャグ配列から戻す
      }
    }

    return answer;
  }
  
}