Problem:
Score : 800 points

Problem Statement

Niwango-kun, an employee of Dwango Co., Ltd., likes Niconico TV-chan, so he collected a lot of soft toys of her and spread them on the floor.

Niwango-kun has N black rare soft toys of Niconico TV-chan and they are spread together with ordinary ones. He wanted these black rare soft toys to be close together, so he decided to rearrange them.

In an infinitely large two-dimensional plane, every lattice point has a soft toy on it. The coordinates (x_i,y_i) of N black rare soft toys are given. All soft toys are considered to be points (without a length, area, or volume).

He may perform the following operation arbitrarily many times:

Put an axis-aligned square with side length D, rotate the square by 90 degrees with four soft toys on the four corners of the square. More specifically, if the left bottom corner's coordinate is (x, y), rotate four points (x,y) \rightarrow (x+D,y) \rightarrow (x+D,y+D) \rightarrow (x,y+D) \rightarrow (x,y) in this order. Each of the four corners of the square must be on a lattice point.

Let's define the scatteredness of an arrangement by the minimum side length of an axis-aligned square enclosing all black rare soft toys. Black rare soft toys on the edges or the vertices of a square are considered to be enclosed by the square.

Find the minimum scatteredness after he performs arbitrarily many operations.

Constraints

2 \leq N \leq 10^5

1 \leq D \leq 1000

0 \leq x_i, y_i \leq 10^9

Given coordinates are pairwise distinct

All numbers given in input are integers

Partial Scores

500 points will be awarded for passing the test set satisfying 1 \leq D \leq 30.

Input

Input is given from Standard Input in the following format:

N D
x_1 y_1
:
x_N y_N

Output

Print the answer.

Sample Input 1

3 1
0 0
1 0
2 0

Sample Output 1

1

Sample Input 2

19 2
1 3
2 3
0 1
1 1
2 1
3 1
4 4
5 4
6 4
7 4
8 4
8 3
8 2
8 1
8 0
7 0
6 0
5 0
4 0

Sample Output 2

4

Sample Input 3

8 3
0 0
0 3
3 0
3 3
2 2
2 5
5 2
5 5

Sample Output 3

4

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.awt.Point;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Main {
	static final long C =  1000000007;
	static final int CY = 1000000000;
	static final int INF = Integer.MAX_VALUE/2;
	StringBuilder sb;

	int[][] G;
	Map<Integer,List<Integer>> Genb = new HashMap<>();
	int V;
	int E;
	int Venb;
	int Eenb;
	long START_TIME;
	static final int LOOPNUM = 2;//何回探すか
	int GenbSize;//Genbグラフの1辺
	int ansSize;//答えが割り当てられるサイズ
	List<Integer> ansIndexs = new ArrayList<Integer>();
	Random rand = new Random();
	public static final int dx[] = { -1, 0, 0, 1 , 0 };
	public static final int dy[] = {  0,-1, 1, 0 , 0 };
	public static final String ds[] = { "U","L", "R", "D" ,""};

	public void calc() {

		sb = new StringBuilder();


		//入力処理
		IO sc = new IO();
		int n = sc.nextInt();
		int d = sc.nextInt();
		int xs[] = new int[n], ys[] = new int[n];
		for (int i=0;i < n; i++) {
			xs[i] = sc.nextInt();
			ys[i] = sc.nextInt();
		}
		int ans = 0;
		int[][] map = new int[d][d];
		for (int i=0; i < n; i++) {
			int nx = xs[i]%d,ny = ys[i] %d;
			map[nx][ny]++;
		}
		int ax = 0,ay = 0;
		for (int x=0; x < d;x++) {
			for (int y=0;y < d; y++) {
				int num = map[y][x];
				if (num ==0 ) continue;
				int pow = (int)Math.sqrt(num);
				int px = pow-1, py = pow-1;
				boolean f = false;
				
				if (pow*(pow+1) <num) {
					py++;
					px++;
				}else if (pow*pow <num) {
					int modx = Math.abs(x-ax%d);
					int mody = Math.abs(y-ay%d);
					if (Math.min(d-modx, modx) < Math.min(d - mody, mody)) {
						px++;
					}else {
						py++;
					}
				}
				//System.err.printf("x%d:%d:%d:%d:n%d:%d:%d:%d\n",x,y,px,py,num,ax,ay,ans);
				int a1x = Math.floorDiv(ax-x, d)*d+x;
				int a2x =( Math.floorDiv(ax-x, d)+1)*(d)+x;
				int a1y = Math.floorDiv(ay-y, d)*d+y;
				int a2y = (Math.floorDiv(ay-y, d)+1)*(d)+y;
				int a1xn = Math.max(ax+ans,a1x+px*d) - Math.min(ax, a1x);
				int a2xn = Math.max(ax+ans,a2x+px*d) - Math.min(ax, a2x);
				int a1yn = Math.max(ay+ans,a1y+py*d) - Math.min(ay, a1y);
				int a2yn = Math.max(ay+ans,a2y+py*d) - Math.min(ay, a2y);
				//System.err.printf("x%d:%d:%d:%d:n%d:%d:%d:%d\n",a1x,a1xn,a2x,a2xn,a1y,a1yn,a2y,a2yn);
				if (a1xn < a2xn) {
					ax = Math.min(ax,a1x);
					ans = Math.max(ans,a1xn);
				}else {
					ax = Math.min(ax,a2x);
					ans = Math.max(ans,a2xn);
				}
				if (a1yn < a2yn) {
					ay = Math.min(ay,a1y);
					ans = Math.max(ans,a1yn);
				}else {
					ay = Math.min(ay,a2y);
					ans = Math.max(ans,a2yn);
				}
			}
		}
		System.err.printf("%d:%d\n",ax,ay);
		System.out.println(ans);

	}
	StringBuilder twoArrayToString(int[][] a) {
		StringBuilder s = new StringBuilder();
		
		for (int i=0; i < a.length; i++) {
			s.append( arrayToString(a[i]));
			if (i != a.length-1) {
				s.append("\n");
			}
		}
		return s ;
	}
	//配列の空白区切り文字化(最後にスペース無しの)
		StringBuilder arrayToString(int[] a) {
			StringBuilder s = new StringBuilder();

			for (int i=0; i < a.length; i++) {
				s.append( a[i]);
				if (i != a.length-1) {
					s.append(" ");
				}
			}
			return s ;
		}
		StringBuilder twoArrayToString(long[][] a) {
			StringBuilder s = new StringBuilder();
			
			for (int i=0; i < a.length; i++) {
				s.append( arrayToString(a[i]));
				if (i != a.length-1) {
					s.append("\n");
				}
			}
			return s ;
		}
		//配列の空白区切り文字化(最後にスペース無しの)
			StringBuilder arrayToString(long[] a) {
				StringBuilder s = new StringBuilder();

				for (int i=0; i < a.length; i++) {
					s.append( a[i]);
					if (i != a.length-1) {
						s.append(" ");
					}
				}
				return s ;
			}
	public static void main(String[] args) {
		Main main = new Main();
		main.calc();

	}
}

class IO extends PrintWriter {
	private final InputStream in;
	private final byte[] buffer = new byte[1024];
	private int ptr = 0;
	private int buflen = 0; 

	public IO() { this(System.in);}
	public IO(InputStream source) { super(System.out); this.in = source;}
	private boolean hasNextByte() {
		if (ptr < buflen) {
			return true;
		}else{
			ptr = 0;
			try {
				buflen = in.read(buffer);
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (buflen <= 0) {
				return false;
			}
		}
		return true;
	}
	private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
	private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
	private static boolean isNewLine(int c) { return c == '\n' || c == '\r';}
	public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
	public boolean hasNextLine() { while(hasNextByte() && isNewLine(buffer[ptr])) ptr++; return hasNextByte();}
	public String next() {
		if (!hasNext()) {
			throw new NoSuchElementException();
		}
		StringBuilder sb = new StringBuilder();
		int b = readByte();
		while(isPrintableChar(b)) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}
	public char[] nextCharArray(int len) {
		if (!hasNext()) {
			throw new NoSuchElementException();
		}
		char[] s = new char[len];
		int i = 0;
		int b = readByte();
		while(isPrintableChar(b)) {
			if (i == len) {
				throw new InputMismatchException();
			}
			s[i++] = (char) b;
			b = readByte();
		}
		return s;
	}
	public String nextLine() {
		if (!hasNextLine()) {
			throw new NoSuchElementException();
		}
		StringBuilder sb = new StringBuilder();
		int b = readByte();
		while(!isNewLine(b)) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}
	public long nextLong() {
		if (!hasNext()) {
			throw new NoSuchElementException();
		}
		long n = 0;
		boolean minus = false;
		int b = readByte();
		if (b == '-') {
			minus = true;
			b = readByte();
		}
		if (b < '0' || '9' < b) {
			throw new NumberFormatException();
		}
		while(true){
			if ('0' <= b && b <= '9') {
				n *= 10;
				n += b - '0';
			}else if(b == -1 || !isPrintableChar(b)){
				return minus ? -n : n;
			}else{
				throw new NumberFormatException();
			}
			b = readByte();
		}
	}
	public int nextInt() {
		long nl = nextLong();
		if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) {
			throw new NumberFormatException();
		}
		return (int) nl;
	}
	public char nextChar() {
		if (!hasNext()) {
			throw new NoSuchElementException();
		}
		return (char) readByte();
	}
	public double nextDouble() { return Double.parseDouble(next());}
	public int[] nextIntArray(int n) { int[] a = new int[n]; for(int i=0;i<n;i++) a[i] = nextInt(); return a;}
	public long[] nextLongArray(int n) { long[] a = new long[n]; for(int i=0;i<n;i++) a[i] = nextLong(); return a;}
	public double[] nextDoubleArray(int n) { double[] a = new double[n]; for(int i=0;i<n;i++) a[i] = nextDouble(); return a;}
	public void nextIntArrays(int[]... a) { for(int i=0;i<a[0].length;i++) for(int j=0;j<a.length;j++) a[j][i] = nextInt();}
	public int[][] nextIntMatrix(int n,int m) { int[][] a = new int[n][]; for(int i=0;i<n;i++) a[i] = nextIntArray(m); return a;}
	public char[][] nextCharMap(int n,int m) { char[][] a = new char[n][]; for(int i=0;i<n;i++) a[i] = nextCharArray(m); return a;}
	public void close() { super.close(); try {in.close();} catch (IOException e) {}}
}