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 C (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#define D_DCNT_MAX		100000									// 最大人形数

// 内部構造体 - 人形情報
typedef struct Doll {
	int miX, miY;												// 座標
	int miDCnt;													// 人形数
	int miXYCnt;												// チェック方向数
} Doll;

// 内部変数
static FILE *szpFpI;											// 入力
static int siSize;												// 正方形サイズ
static Doll sz1Doll[D_DCNT_MAX];								// 人形
static int siDCnt;												// 人形数

// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpA;
	static int siTNo;
#endif

// １行出力
int
fOutLine(
	char *pcpLine				// <I> １行
)
{
	char lc1Buf[1024];

#ifdef D_TEST
	lc1Buf[0] = '\0';
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, pcpLine)) {
		siRes = -1;
	}
#else
	printf("%s", pcpLine);
#endif

	return 0;
}

// 最小値 - 取得
int
fGetMinI(
	int piVal1					// <I> 値１
	, int piVal2				// <I> 値２
)
{
	if (piVal1 < piVal2) {
		return piVal1;
	}
	else {
		return piVal2;
	}
}

// 比較関数 - 座標昇順
int
fCmpFncXuYu(
	const void *pzpVal1			// <I> 値１
	, const void *pzpVal2		// <I> 値２
)
{
	Doll *lzpVal1 = (Doll *)pzpVal1;
	Doll *lzpVal2 = (Doll *)pzpVal2;

	// 座標昇順
	if (lzpVal1->miX > lzpVal2->miX) {
		return 1;
	}
	else if (lzpVal1->miX < lzpVal2->miX) {
		return -1;
	}
	if (lzpVal1->miY > lzpVal2->miY) {
		return 1;
	}
	else if (lzpVal1->miY < lzpVal2->miY) {
		return -1;
	}

	return 0;
}

// 比較関数 - 個数降順
int
fCmpFncCu(
	const void *pzpVal1			// <I> 値１
	, const void *pzpVal2		// <I> 値２
)
{
	Doll *lzpVal1 = (Doll *)pzpVal1;
	Doll *lzpVal2 = (Doll *)pzpVal2;

	// 個数降順
	if (lzpVal1->miDCnt > lzpVal2->miDCnt) {
		return -1;
	}
	else if (lzpVal1->miDCnt < lzpVal2->miDCnt) {
		return 1;
	}

	return 0;
}

// 配列 - 重複カット
int
fCutDpl(
	Doll *pzpArray				// <IO> 配列
	, int *pipACnt				// <IO> 配列数
)
{
	int i;
	int liTo = 1;
	int liDCnt = 0;
	for (i = 1; i < *pipACnt; i++) {
		if (pzpArray[i].miX == pzpArray[liTo - 1].miX && pzpArray[i].miY == pzpArray[liTo - 1].miY) {
			pzpArray[liTo - 1].miDCnt++;
			liDCnt++;
		}
		else {
			pzpArray[liTo] = pzpArray[i];
			liTo++;
		}
	}

	*pipACnt -= liDCnt;

	return liDCnt;
}

// 内包できるかチェック
int
fAbleIn(
	Doll *pzpDoll				// <I> 開始人形
	, int piSize				// <I> サイズ
)
{
	int i;

	for (i = 0; i < siDCnt; i++) {
		int liXYCnt = 0;

		// X方向
		int liPos = sz1Doll[i].miX;
		if (liPos < pzpDoll->miX) {
			liPos += siSize;
		}
		if (liPos <= pzpDoll->miX + piSize) {
			liXYCnt++;
		}

		// Y方向
		liPos = sz1Doll[i].miY;
		if (liPos < pzpDoll->miY) {
			liPos += siSize;
		}
		if (liPos <= pzpDoll->miY + piSize) {
			liXYCnt++;
		}

		// 内包できない
		if (sz1Doll[i].miXYCnt > liXYCnt) {
			return -1;
		}
	}

	return 0;
}

// 追加サイズ - 取得
int
fGetSize(
	Doll *pzpDoll				// <I> 開始人形
)
{
	int liRet;

	// 範囲を絞る
	int liMin = 0;
	int liMax = siSize;
	int liSize;
	while (liMin <= liMax) {
		int liAvg = (liMin + liMax) / 2;

		// 内包できるかチェック
		liRet = fAbleIn(pzpDoll, liAvg);
		if (liRet == 0) {
			liMax = liAvg - 1;
			liSize = liAvg;
		}
		else {
			liMin = liAvg + 1;
		}
	}

	return liSize;
}

// 実行メイン
int
fMain(
)
{
	int i;
	char lc1Buf[1024];

	// 人形数・正方形サイズ - 取得
	fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
	sscanf(lc1Buf, "%d%d", &siDCnt, &siSize);

	// 人形位置 - 取得
	for (i = 0; i < siDCnt; i++) {
		fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
		sscanf(lc1Buf, "%d%d", &sz1Doll[i].miX, &sz1Doll[i].miY);
		sz1Doll[i].miX %= siSize;
		sz1Doll[i].miY %= siSize;
		sz1Doll[i].miDCnt = 1;
	}

	// 人形 - 集約
	qsort(sz1Doll, siDCnt, sizeof(Doll), fCmpFncXuYu);
	fCutDpl(sz1Doll, &siDCnt);

	// 最低正方形数 - 取得
	qsort(sz1Doll, siDCnt, sizeof(Doll), fCmpFncCu);
	int liSCnt;
	for (liSCnt = 0; ; liSCnt++) {
		if (sz1Doll[0].miDCnt <= (liSCnt + 1) * (liSCnt + 1)) {
			break;
		}
	}

	// チェック方向数 - セット
	int liCCnt1 = liSCnt * liSCnt;
	int liCCnt2 = liSCnt * (liSCnt + 1);
	for (i = 0; i < siDCnt; i++) {
		if (sz1Doll[i].miDCnt > liCCnt2) {
			sz1Doll[i].miXYCnt = 2;
		}
		else if (sz1Doll[i].miDCnt > liCCnt1) {
			sz1Doll[i].miXYCnt = 1;
		}
		else {
			siDCnt = i;
			break;
		}
	}

	// 最小追加サイズ - 取得
	int liMin = INT_MAX;
	for (i = 0; i < siDCnt; i++) {
		int liSize = fGetSize(&sz1Doll[i]);
		liMin = fGetMinI(liMin, liSize);
	}

	return liSCnt * siSize + liMin;
}

// １回実行
int
fOne(
)
{
	int liRet;
	char lc1Buf[1024];

	// 入力 - セット
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", siTNo);
	szpFpI = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", siTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#else
	szpFpI = stdin;
#endif

	// 実行メイン
	liRet = fMain();

	// 出力
	sprintf(lc1Buf, "%d\n", liRet);
	fOutLine(lc1Buf);

	// 残データ有無
#ifdef D_TEST
	lc1Buf[0] = '\0';
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, "")) {
		siRes = -1;
	}
#endif

	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpI);
	fclose(szpFpA);
#endif

	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", siTNo);
	}
	else {
		printf("NG %d\n", siTNo);
	}
#endif

	return 0;
}

// プログラム開始
int
main()
{

#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		siTNo = i;
		fOne();
	}
#else
	fOne();
#endif

	return 0;
}