import static java.lang.Integer.parseInt;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

class con286_A {

	static int MB = 1 << 20;
	static BufferedReader br = new BufferedReader( new InputStreamReader(System.in, StandardCharsets.US_ASCII), 10*MB);
	static StringTokenizer st;
	
	static void NL() throws Exception {
		st = new StringTokenizer(br.readLine());
	}
	
	static String NT() {
		return st.nextToken();
	}
	
	public static void main(String[] args) throws Exception {
		NL();
		int n = parseInt(NT());
		int d = parseInt(NT());
		cnts = new int[30_001];
		sums = new int[30_001];
		Arrays.fill(cnts, 0);
		Arrays.fill(sums, 0);
		for (int i = 0; i < n; i++) {
			NL();
			int p = parseInt(NT());
			++cnts[p];
		}
		for (int i = 1; i < args.length; i++) {
			sums[i] = sums[i-1] + cnts[i];
		}
		System.out.println(solve(n, d, cnts));
	}

	static int[] cnts;
	static int[] sums;
	
	private static int solve(int n, int d, int[] cnts) {
		cache.clear();
		int res = dp(d, d);
		System.out.println(getSize());
		return res;
	}

	
	private static int getSize() {
		int res = 0;
		for (int in : cache.keySet()) {
			res += cache.get(in).size();
		}
		return res;
	}

	private static int dp(int pos, int l) {
		if (pos >= cnts.length) return 0;

		if ( l == 1 ) {
			// sums pos - end
			return sums[30_000] - sums[pos-1];
		}
//		if (sums[30_000] - sums[pos-1] < m) {
//			return 0;
//		}
		// l > 1
		
		Integer c = getFromCache(pos, l);
		if (c != null) return c;
		
		int res = cnts[pos];
		int max = -1;
		int c3 = dp(pos + l - 1, l-1);
		max = c3;
		if (l >= 4) {
			int c1 = dp(pos + l, l);
			if (max < c1) max = c1;
			int c2 = dp(pos + l + 1, l + 1);
			max = Math.max(max, c2);
		}
		
		int val = res + max;
		setToCache(pos, l, val);
		return val;
	}

	private static void setToCache(int pos, int l, int val) {
		TreeMap<Integer, Integer> inMap = cache.get(pos);
		if (inMap == null) {
			inMap = new TreeMap<>();
			cache.put(pos, inMap);
		}
		inMap.put(l, val);
	}

	static TreeMap<Integer, TreeMap<Integer, Integer>> cache = new TreeMap<>();
	
	private static Integer getFromCache(int pos, int l) {
		TreeMap<Integer, Integer> inMap = cache.get(pos);
		if (inMap == null ) return null;
		return inMap.get(l);
	}
	
}
