One common way of digitalizing sound is to record sound intensity at particular time moments. For each time moment intensity is recorded as a non-negative integer. Thus we can represent a sound file as an array of n non-negative integers.

If there are exactly K distinct values in the array, then we need k = ⌈ log_{2} K ⌉ bits to store each value. It then takes nk bits to store the whole file.

To reduce the memory consumption we need to apply some compression. One common way is to reduce the number of possible intensity values. We choose two integers l ≤ r, and after that all intensity values are changed in the following way: if the intensity value is within the range [l;r], we don't change it. If it is less than l, we change it to l; if it is greater than r, we change it to r. You can see that we lose some low and some high intensities.

Your task is to apply this compression in such a way that the file fits onto a disk of size I bytes, and the number of changed elements in the array is minimal possible.

We remind you that 1 byte contains 8 bits.

k = ⌈ log_{2} K ⌉ is the smallest integer such that K ≤ 2^{k}. In particular, if K = 1, then k = 0.

Input

The first line contains two integers n and I (1 ≤ n ≤ 4 ⋅ 10^{5}, 1 ≤ I ≤ 10^{8}) — the length of the array and the size of the disk in bytes, respectively.

The next line contains n integers a_{i} (0 ≤ a_{i} ≤ 10^{9}) — the array denoting the sound file.

Output

Print a single integer — the minimal possible number of changed elements.

Examples

Input


6 1
2 1 2 3 4 3


Output


2


Input


6 2
2 1 2 3 4 3


Output


0


Input


6 1
1 1 2 2 3 3


Output


2

Note

In the first example we can choose l=2, r=3. The array becomes 2 2 2 3 3 3, the number of distinct elements is K=2, and the sound file fits onto the disk. Only two values are changed.

In the second example the disk is larger, so the initial file fits it and no changes are required.

In the third example we have to change both 1s or both 3s.


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.StringTokenizer;
public class Main {

	static ArrayList<Integer>[] adjList;
	static PrintWriter pw = new PrintWriter(System.out);
 static int[] arrSorted;
	public static void main(String[] args) throws IOException, InterruptedException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		st =new StringTokenizer(bf.readLine());
		int n= Integer.parseInt(st.nextToken());
		int I=Integer.parseInt(st.nextToken());
		I*=8;
		int segLen=I/n;
			segLen=1<<segLen;
		HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
		int[] arr = new int[n];
		st= new StringTokenizer(bf.readLine());
		 arrSorted=new int[n];
		for(int i=0;i<n;i++) {
		arr[i]=Integer.parseInt(st.nextToken());
		arrSorted[i]=arr[i];
		}
		shuffle(arrSorted);
		Arrays.sort(arrSorted);
		
		int c=0;
		map.put(arrSorted[0], c++);
		for(int i=1;i<arrSorted.length;i++) {
			if(!map.containsKey(arrSorted[i])){
				map.put(arrSorted[i], c++);
			}
		}
		
	int[] fq= new int[n];
		for(int i=0;i<n;i++) {
			fq[map.get(arr[i])]++;
		}
		for(int i=1;i<n;i++)
			fq[i]+=fq[i-1];
		
		int max=-1;
		if(segLen==1) {
			max=fq[0];
			for(int i=1;i<n;i++)
				max=Math.max(max, fq[i]-fq[i-1]);
		}else {
			
		
		for(int i=0;i<n;i++) {
			int curr=arr[i];
		
			int idx=binarySearch(curr+segLen-1);
			
			if(idx==-1) {
				max=Math.max(max, fq[i]-((i!=0)?fq[i-1]:0));
			}else {
			
				int endNum=map.get(arrSorted[idx]);
				int startNum=map.get(arr[i]);
				max=Math.max(max,fq[endNum]-((startNum!=0)?fq[startNum-1]:0));
			
			}
			
		
		}
		}
		pw.println(fq[fq.length-1]-max);
		pw.flush();
		pw.close();

}
 public static void shuffle(int[] a)
	{
		int n = a.length;
		for(int i = 0; i < n; i++)
		{
			int r = i + (int)(Math.random() * (n - i));
			int tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

public static double readDouble(String s) {
		StringBuilder sb =new StringBuilder("0");
		boolean neg=false;
		boolean dec=false;
		double div=1;
		int start=0;
		if(s.charAt(0)=='-') {
			neg=true;start++;
		}
		double result=0;
	for(int i=start;i<s.length();i++) {
		if(s.charAt(i)=='.') {
			result+=Long.parseLong(sb.toString());
	
			sb =new StringBuilder("0");
			dec=true;
		}else {
			sb.append(s.charAt(i));
			if(dec)
				div*=10;
		}
	}

	result+=Long.parseLong(sb.toString()) / div;
	return (neg)?-1*result:result;
}
public static int gcd(int a,int b) {
	if(a==0)return b;
	return gcd(b%a,a);
}
public static int pow(int a, int n) {
	int res=1;
	while(n>0) {
		if((n&1)==1)
			res*=a;
		a*=a;
		n>>=1;
	}
	return res;
}


//	public static boolean isPrimeNum(int n) {
//		if(n<isPrime.length)return isPrime[n];
//		int p=primes.get(0);
//		int idx=0;
//		while(p*p<=n) {
//			if(n%p==0)return false;
//		p=primes.get(++idx);
//		}
//		return true;
//	}

	public static int binarySearch(int x) {
		int start=0;
		int end=arrSorted.length-1;
		while(end-start+1>2) {
			int mid =(start+end)>>1;
			int midelem=arrSorted[mid];
			if(arrSorted[mid-1]<=x&&midelem>x)return mid-1;
			if(arrSorted[mid]==x)return mid;
			if(midelem<x) start=mid;
			else
				end=mid;
		}
		if(arrSorted[end]<=x)return end;
		return (arrSorted[start]<=x)?start:-1;
	}
//public static int binarySearch(int x) {
//	int start=0;
//	int end=pf.length-1;
//	while(end-start+1>2) {
//		int mid =(start+end)>>1;
//		int midelem=pf[mid];
//		if(midelem==x)return mid;
//		if(midelem<x) start=mid;
//		else
//			end=mid;
//	}
//	if(pf[end]==x)return end;
//	if(pf[start]==x)return start;
//	return -1;
//
//}

	static boolean[] isPrime;
	static ArrayList<Integer> primes;
	static ArrayList<Integer>[] factors;//factors[i] if i=9 {3,2} 

	
public static void ModifiedSieveForFactors(int N) {// O( n log( log n ) )
		isPrime= new boolean[N+1];//u can save half the memory by neglecting all even numbers since they aren't primes
	primes= new ArrayList<>(N+1);
		Arrays.fill(isPrime, true);
		factors = new ArrayList[N+1];
		for(int i=0;i<=N;i++)
			factors[i]=new ArrayList<>();
		isPrime[0]=isPrime[1]=false;
		factors[1].add(2);
		factors[1].add(0);
		for(int i=2;i<=N;i++) {
			if(isPrime[i]) {
				for(int j=i;j<=N;j+=i) {
					isPrime[j]=false;
					int k=j;
					int count=0;
					while(k%i==0) {
						count++;
						k/=i;
					}
					factors[j].add(i);
					factors[j].add(count);
				}
				isPrime[i]=true;
			}
		}
		for(int i=0;i<isPrime.length;i++) {
			if(isPrime[i])primes.add(i);
		}
	}
public static int getPth(long M) {
	if(M<factors.length) {
		ArrayList<Integer>factor= factors[(int)M];
		int prev=factor.get(1);
		for(int i=3;i<factor.size();i+=2) {
			prev=gcd(prev,factor.get(i));
		}
		return prev;
	}else {
		int p=primes.get(0);
		int idx=0;
		boolean firstTime=true;
		int prev=1;
		while(p*1l*p<=M) {
			int count=0;
			boolean entered=false;
			while(M%p==0) {
				M/=p;
				count++;
				entered=true;
				
			}
			if(firstTime&&entered) {
				prev=count;
				firstTime=false;
			}else if(entered)prev=gcd(prev,count);
				
			p=primes.get(++idx);
			}
			
			if(M!=1)
				return 1;
			return prev;
	}
		
	}

	public static void sieve(int N) {// O( n log( log n ) )
		isPrime= new boolean[N+1];//u can save half the memory by neglecting all even numbers since they aren't primes
		primes= new ArrayList<>(N);
		Arrays.fill(isPrime, true);
		isPrime[0]=isPrime[1]=false;
		for(int i=2;i*i<=N;i++) {
			if(isPrime[i]) {
				for(int j=i*i;j<=N;j+=i) {
					isPrime[j]=false;
				}
			}
		}
		
		for(int i=2;i<=N;i++)
			if(isPrime[i])
				primes.add(i);
		
	}

	static long[] lcmCard;
	public static void LCMCard(int N) {//modified sieve
		lcmCard=new long[N+1];
		Arrays.fill(lcmCard,1);
		primes=new ArrayList<>();
		for(int i=2;i<=N;i++) {
			if(lcmCard[i]==1) {
				primes.add(i);
				for(int j =i;j<=N;j+=i) {
					int k=j;
					int count=0;
					while(k%i==0) {
						k/=i;
						count++;
					}
					lcmCard[j]*=((count<<1)+1);
				}
			}
		}
		
	}
	public static long findCard(int N) {
		if(N<lcmCard.length)return lcmCard[N];
		int p=primes.get(0);
		int idx=0;
		long r=1;
		while(p*p<=N) {
			int count=0;
			while(N%p==0) {
				N/=p;
				count++;
			}
			r*=((count<<1)+1);
			p=primes.get(++idx);
		}
		
		if(N!=1) {
			r*=3;
		}
		return r;
		
	}


	public static void addEdge(int a, int b) {
		adjList[a].add(b);
		adjList[b].add(a);
	}
	static class FenwickTree {//one-based DS
	//it's for reversable operations to be able to find a range but if u always want from 1 to j so it will work
	
int[] ft;// note it must be 1 based because ur first elem FT[1] is A[1 -LSON(1)]  (i'm kidding it can also be 0 based ) 
//to be consistent with segment tree let it to be 1 based
int n;

public FenwickTree(int n) {
	this.n=n;
	ft= new int[n+1];
}

public int LSONE(int i) {
	return i&(-i);
}

public void update_point(int  k ,int val) {//O(log n) because K will at worst case incremented with the number of ones in n so if to get number of bit
	// it's log(n)
	while(k<=n) {
		ft[k]+=val;
		k+=LSONE(k);
	}
}
public void update_range(int i , int j ,int val) {
	update_point(i, val);
	update_point(j+1, -val);//the inverse of the operation in our case it's subtraction
	
}
public int query(int k) {// we keep adding ft[k]+ft[k']+ft[k"]+... where k' =k-LSONE(K) till k==0 it's also O(log(n))
	int sum =0;
	while(k>0) {
		sum+=ft[k];
		k-=LSONE(k);
	}
	return sum;
}

public int query(int i , int j) {
	return query(j) - ((i<=1)?0:query(i-1));
}

public int pointQuery(int i) { //less than log n == no. of first zero bits till LSOne 
		int sum=ft[i];
		
		if(i>0) {
		//int z=(i)-(LSONE(i));	
			int z= i ^(i&-i); // turn off the LSONE
			i--;
		while(i!=z) {
			sum-=ft[i];
			i-=LSONE(i);
		}
		
		}
		return sum;
}



}


	
static public class SegmentTree {

		int N;
		int[] array;
		int[] lazy;
		int[] sTree;
		int[] idx;
//public node combine(node a,node b) {
//	int maxPos=Math.min(Math.abs(a.leftOpen),Math.abs( b.rightOpen));
//	return new node(a.leftOpen-maxPos+b.leftOpen,a.rightOpen+b.rightOpen-maxPos,a.sum+b.sum+maxPos);
//}
	
	public SegmentTree(int[] arr) {// note arr must be 1 based arr
			array = arr;
			N = arr.length - 1;// arr must be power of 2 and 1 based array
			sTree = new int[N << 1]; // no of nodes is 2N-1 but we add 1 to be 1 index
			lazy = new int[N << 1];
			idx=new int[N<<1];
			build(1, 1, N);

		}

	
	public void build(int v, int b, int e) {// o(N)
			if (b == e) {
				sTree[v] = array[b];
				idx[v]=b;
			} else {
				int mid = (b + e) >> 1;
				build((v << 1), b, mid);
				build((v << 1) | 1, mid + 1, e);
				sTree[v] =Math.max( sTree[v << 1] , sTree[(v << 1) | 1]);
				idx[v]=(sTree[v<<1|1]>=sTree[v<<1])?idx[v<<1|1]:idx[v<<1];
			}
		}

		public int query(int i, int j) {// O(2log(n))
			return query(1, 1, N, i, j);
		}

		public int getIdx(long max, int node) {
			int r = node;
			while (node < N - 1) {
				if (sTree[node << 1] == max)
					node <<= 1;
				else if (sTree[node << 1 | 1] == max)
					node = node << 1 | 1;
			}
			return node - (N - 1);
		}

		public int query(int node, int b, int e, int i, int j) {
			if (b > j || e < i)
				return 0;
			if (b >= i && e <= j) {
				return idx[node];

			}
			int mid = (b + e) >> 1;

			//propagate(node, b, mid, e);
			int leftChild = query(node << 1, b, mid, i, j);
			int rightChild = query((node << 1) | 1, mid + 1, e, i, j);

			return  array[rightChild]>=array[leftChild]?rightChild:leftChild;

		}

		public void set_point(int idx, int val) {

			idx += N - 1;
			sTree[idx] = val;
			boolean or = true;
			while (idx > 1) {
				idx >>= 1;
				sTree[idx] = sTree[idx << 1] + sTree[idx << 1 | 1];
			}
		}

		public void update_point(int idx, int val) {
			idx += N - 1;
			sTree[idx] += val;
			while (idx > 1) {
				idx >>= 1;// divide by 2 to get the parent
				sTree[idx] = sTree[(idx << 1)] + sTree[(idx << 1) | 1];
			}

		}

		public void update_range(int i, int j, int val) {
			update_range(1, 1, N, i, j, val);
		}

		public void update_range(int node, int b, int e, int i, int j, int val) {
			if (e < i || b > j)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;

			} else {

				int mid = (b + e) >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}
		}

		public void propagateAll() {
			propagateAll(1, 1, N);
		}

		public void propagateAll(int node, int b, int e) {

			if (b == e)
				return;
			int mid = (e + b) >> 1;
			propagate(node, b, mid, e);
			propagateAll(node << 1, b, mid);
			propagateAll((node << 1) | 1, mid + 1, e);

		}

		public void propagate(int node, int b, int mid, int e) { // O(1)
			if (lazy[node] == 0 || b == e)
				return;

			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];

			lazy[node] = 0;
		}

	}

	static public class UDS {
		int[] parent, rank, setSize;
		int n;// number of sets
		int maxSet = 1;

		public UDS(int n) {

			this.n = n;
			parent = new int[n];
			rank = new int[n];
			setSize = new int[n];
			Arrays.fill(setSize, 1);
			for (int i = 0; i < n; i++)
				parent[i] = i;
		}

		public boolean unionSet(int i, int j) {
			int p1 = findSet(i);
			int p2 = findSet(j);

			if (p1 != p2) {
				n--;
				if (rank[p1] < rank[p2]) {
					parent[p1] = p2;
					setSize[p2] += setSize[p1];
					maxSet = Math.max(maxSet, setSize[p2]);
				} else {
					parent[p2] = p1;
					setSize[p1] += setSize[p2];
					maxSet = Math.max(maxSet, setSize[p1]);
					if (rank[p1] == rank[p2])
						rank[p1]++;
				}
				return true;
			}
			return false;
		}

		public int sizeOfSet(int i) {
			return setSize[findSet(i)];
		}

		public int numDisjointSets() {
			return n;
		}

		public boolean isSameSet(int i, int j) {
			return findSet(i) == findSet(j);
		}

		public int findSet(int i) {
			return (parent[i] == i) ? i : (parent[i] = findSet(parent[i]));
		}
	}


}
