Problem:
Score : 400 points

Problem Statement

Snuke lives in another world, where slimes are real creatures and kept by some people.
Slimes come in N colors. Those colors are conveniently numbered 1 through N.
Snuke currently has no slime. His objective is to have slimes of all the colors together.

Snuke can perform the following two actions:

Select a color i (1≤i≤N), such that he does not currently have a slime in color i, and catch a slime in color i. This action takes him a_i seconds.

Cast a spell, which changes the color of all the slimes that he currently has. The color of a slime in color i (1≤i≤N-1) will become color i+1, and the color of a slime in color N will become color 1. This action takes him x seconds.

Find the minimum time that Snuke needs to have slimes in all N colors.

Constraints

2≤N≤2,000

a_i are integers.

1≤a_i≤10^9

x is an integer.

1≤x≤10^9

Input

The input is given from Standard Input in the following format:

N x
a_1 a_2 ... a_N

Output

Find the minimum time that Snuke needs to have slimes in all N colors.

Sample Input 1

2 10
1 100

Sample Output 1

12

Snuke can act as follows:

Catch a slime in color 1. This takes 1 second.

Cast the spell. The color of the slime changes: 1 → 2. This takes 10 seconds.

Catch a slime in color 1. This takes 1 second.

Sample Input 2

3 10
100 1 100

Sample Output 2

23

Snuke can act as follows:

Catch a slime in color 2. This takes 1 second.

Cast the spell. The color of the slime changes: 2 → 3. This takes 10 seconds.

Catch a slime in color 2. This takes 1 second.

Cast the soell. The color of each slime changes: 3 → 1, 2 → 3. This takes 10 seconds.

Catch a slime in color 2. This takes 1 second.

Sample Input 3

4 10
1 2 3 4

Sample Output 3

10

Snuke can act as follows:

Catch a slime in color 1. This takes 1 second.

Catch a slime in color 2. This takes 2 seconds.

Catch a slime in color 3. This takes 3 seconds.

Catch a slime in color 4. This takes 4 seconds.

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.StringTokenizer;
class Main{
	public static void main(String[] args) {
		SC sc=new SC(System.in);
		int N=sc.nextInt();
		int x=sc.nextInt();
		long min=Long.MAX_VALUE;
		Segtree sg=new Segtree(N);
		sg.fill(Integer.MAX_VALUE);
		for(int i=0; i<N; i++) {
			int tmp=sc.nextInt();
			sg.update(i,tmp);
		}
		for(int i=0; i<N; i++) {//呪文を呼ぶ回数
			long tmp=((long)i)*((long)x);
			long ts=0;
			for(int j=0; j<N; j++) {
				if(j-i<0) {
					//にくかんに分かれる
					int a1=0;
					int a2=j;
					int b1=N+(j-i);
					int b2=N;
					ts+=((long)Math.min(sg.getmin(a1,a2, 0, 0, (sg.length()+1)/2), sg.getmin(b1,b2, 0, 0, (sg.length()+1)/2)));
				}
				else {
					ts+=((long)sg.getmin(j-i, j, 0, 0, (sg.length()+1)/2));
				}
			}
			tmp+=ts;
			min=Math.min(min, tmp);
		}
		pl(min);
	}
	static class Segtree{
		int[] Segtree;
		public Segtree(int vol){
			int truevol=calc_vol(vol);		//vol以上で最も小さい2ベキを求める
			Segtree=new int[truevol*2-1];
			for(int i=0; i<truevol*2-1; i++) {
				Segtree[i]=0;
			}
			//pl(truevol*2-1);
		}
		public void fill(int num) {		//特定の値にフィルする
			for(int i=0; i<Segtree.length; i++) {
				Segtree[i]=num;
				//pl(i+" "+Segtree[i]);
			}
		}
		public void update(int elem,int num) {
			int leaf=elem-1+(length()+1)/2;	//更新する要素の添字
			Segtree[leaf]=num;
			boolean zero=false;	//0までたどり着いたか
			while(leaf>0) {
				leaf=getParent(leaf);	//上に（根の方）近づく
				Segtree[leaf]=Math.min(Segtree[leaf*2+1],Segtree[leaf*2+2]);
			}
		}
		public int getmin(int a,int b,int k,int l,int r) {
			//pl(a+" "+b+" "+k+" "+l+" "+r);
			if(r <= a || b < l) return Integer.MAX_VALUE; //区間が交わっていないなら0
			if(a <= l && r-1 <= b) return Segtree[k]; //[l,r)が完全に[a,b)に内包されているならそのノードを返す
			else {
				int vl = getmin(a, b, k*2+1, l, (l+r)/2);
				int vr = getmin(a, b, k*2+2, (l+r)/2, r);
				return Math.min(vl , vr);
			}
		}
		public int calc_vol(int vol) {	//2のべき乗の値のサイズにする
			int beki=0;
			int tmp=1;
			while(vol>=tmp) {
				tmp*=2;
				if(tmp==vol) {
					break;
				}
				beki++;
			}
			return tmp;
		}
		public int getParent(int num) {	//親取得
			return (num-1)/2;
		}
		public int getChild(int num) {	//子取得
			return num*2+1;	//子は2つあるが、そのうち数が若いほう
		}
		public void add(int elem,int num) {	//elem番目の要素にnum足す(elemは0オリジン)
			int leaf=elem-1+(length()+1)/2;	//更新するセグ木の末端
			boolean zero=false;	//0までたどり着いたか
			while(!zero && leaf>=0) {
				//pl(leaf);
				Segtree[leaf]+=num;
				if(leaf==0) {
					zero=true;
				}
				leaf=getParent(leaf);	//上に（根の方）近づく
			}
		}
		public int sum(int a, int b, int k, int l, int r) {//sum(a, b, 0, 0, seg.tree.length/2)
			//[a,b]の要素の和を求める
			//pl(a+" "+b+" "+k+" "+l+" "+r);
			if(r <= a || b < l) return 0; //区間が交わっていないなら0
			if(a <= l && r-1 <= b) return Segtree[k]; //[l,r)が完全に[a,b)に内包されているならそのノードを返す
			else {
				int vl = sum(a, b, k*2+1, l, (l+r)/2);
				int vr = sum(a, b, k*2+2, (l+r)/2, r);
				return vl + vr;
			}
		}
		public int length() {
			return Segtree.length;
		}
	}
	static class SC {
		private BufferedReader reader = null;
		private StringTokenizer tokenizer = null;
		public SC(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
		}
		public String next() {
			if (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new UncheckedIOException(e);
				}
			}
			return tokenizer.nextToken();
		}
		public int nextInt() {
			return Integer.parseInt(next());
		}
		public long nextLong() {
			return Long.parseLong(next());
		}
	}
	public static void pl(Object o) {
		System.out.println(o);
	}
	public static void pl() {
		System.out.println();
	}
	public static void p(Object o) {
		System.out.print(o);
	}
}