Problem:
Score : 400 points

Problem Statement

There is a bar of chocolate with a height of H blocks and a width of W blocks.
Snuke is dividing this bar into exactly three pieces.
He can only cut the bar along borders of blocks, and the shape of each piece must be a rectangle.

Snuke is trying to divide the bar as evenly as possible.
More specifically, he is trying to minimize S_{max} - S_{min}, where S_{max} is the area (the number of blocks contained) of the largest piece, and S_{min} is the area of the smallest piece.
Find the minimum possible value of S_{max} - S_{min}.

Constraints

2 ≤ H, W ≤ 10^5

Input

Input is given from Standard Input in the following format:

H W

Output

Print the minimum possible value of S_{max} - S_{min}.

Sample Input 1

3 5

Sample Output 1

0

In the division below, S_{max} - S_{min} = 5 - 5 = 0.

Sample Input 2

4 5

Sample Output 2

2

In the division below, S_{max} - S_{min} = 8 - 6 = 2.

Sample Input 3

5 5

Sample Output 3

4

In the division below, S_{max} - S_{min} = 10 - 6 = 4.

Sample Input 4

100000 2

Sample Output 4

1

Sample Input 5

100000 100000

Sample Output 5

50000

Solution in C (GCC 5.4.1) (judge verdict: Accepted)

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
 
// 内部変数
static long long slMax;											// 最大値
static long long slMin;											// 最小値
static int siDF;												// 差
 
// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpT, *szpFpA;
#endif
 
// 値の３分割
int
fDiv3(
	int piVal					// <I> 値
	, int *pipRet				// <O> ３つの値
)
{
	int i;
 
	// 商
	int liVal = piVal / 3;
	for (i = 0; i < 3; i++) {
		pipRet[i] = liVal;
	}
 
	// 余り
	liVal = piVal % 3;
	for (i = 0; i < liVal; i++) {
		pipRet[i]++;
	}
 
	return 0;
}
 
// 値の２分割 - １：２
int
fDiv2OT(
	int piMode					// <I> [0]左大 [1]:右大
	, int piVal					// <I> 値
	, int *pipRet				// <O> ２つの値
)
{
	// 商
	int liVal = piVal / 3;
	pipRet[0] = liVal;
	pipRet[1] = liVal * 2;
 
	// 余り
	liVal = piVal % 3;
	if (liVal == 1) {
		pipRet[piMode]++;
	}
	else if (liVal == 2) {
		pipRet[0]++;
		pipRet[1]++;
	}
 
	return 0;
}
 
// 値の２分割 - １：１
int
fDiv2OO(
	int piVal					// <I> 値
	, int *pipRet				// <O> ２つの値
)
{
	int i;
 
	// 商
	int liVal = piVal / 2;
	for (i = 0; i < 2; i++) {
		pipRet[i] = liVal;
	}
 
	// 余り
	liVal = piVal % 2;
	if (liVal > 0) {
		pipRet[0]++;
	}
 
	return 0;
}
 
// 最大値・最小値の更新
int
fUpMaxMin(
	long long plVal				// <I> 値
)
{
	// 最大値の更新
	if (slMax < plVal) {
		slMax = plVal;
	}
 
	// 最小値の更新
	if (slMin > plVal) {
		slMin = plVal;
	}
 
	return 0;
}
 
// 差の更新
int
fUpDF(
	int piW1					// <I> 幅１
	, int piH1					// <I> 高さ１
	, int piW2					// <I> 幅２
	, int piH2					// <I> 高さ２
	, int piW3					// <I> 幅３
	, int piH3					// <I> 高さ３
)
{
	// 最大値・最小値の初期化
	slMax = 0;
	slMin = LLONG_MAX;
 
	// 最大値・最小値の更新
	fUpMaxMin((long long)piW1 * (long long)piH1);
	fUpMaxMin((long long)piW2 * (long long)piH2);
	fUpMaxMin((long long)piW3 * (long long)piH3);
 
	// 差の更新
	long long llDF = slMax - slMin;
	if (siDF > llDF) {
		siDF = (int)llDF;
	}
 
	return 0;
}
 
// 実行メイン
int
fMain(
	int piTNo					// <I> テスト番号 1～
)
{
	char lc1Buf[1024], lc1Out[1024];
 
	// データ初期化
	siDF = INT_MAX;												// 差
 
	// テストファイルオープン
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", piTNo);
	szpFpT = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", piTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#endif
 
	// 高さ・幅取得
	int liH, liW;
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpT);
#else
	fgets(lc1Buf, sizeof(lc1Buf), stdin);
#endif
	sscanf(lc1Buf, "%d%d", &liH, &liW);
 
	// パターン１ - 幅３分割
	int li1Val[3];
	fDiv3(liW, li1Val);
	fUpDF(li1Val[0], liH, li1Val[1], liH, li1Val[2], liH);
 
	// パターン２ - 高さ３分割
	fDiv3(liH, li1Val);
	fUpDF(liW, li1Val[0], liW, li1Val[1], liW, li1Val[2]);
 
	// パターン３ - 幅１：２分割後(0)、右側高さ２分割
	fDiv2OT(0, liW, li1Val);
	int li1Val2[2];
	fDiv2OO(liH, li1Val2);
	fUpDF(li1Val[0], liH, li1Val[1], li1Val2[0], li1Val[1], li1Val2[1]);
 
	// パターン４ - 幅１：２分割後(1)、右側高さ２分割
	fDiv2OT(1, liW, li1Val);
	fDiv2OO(liH, li1Val2);
	fUpDF(li1Val[0], liH, li1Val[1], li1Val2[0], li1Val[1], li1Val2[1]);
 
	// パターン５ - 高さ１：２分割後(0)、下側幅２分割
	fDiv2OT(0, liH, li1Val);
	fDiv2OO(liW, li1Val2);
	fUpDF(liW, li1Val[0], li1Val2[0], li1Val[1], li1Val2[1], li1Val[1]);
 
	// パターン６ - 高さ１：２分割後(0)、下側幅２分割
	fDiv2OT(1, liH, li1Val);
	fDiv2OO(liW, li1Val2);
	fUpDF(liW, li1Val[0], li1Val2[0], li1Val[1], li1Val2[1], li1Val[1]);
 
	// 結果セット
	sprintf(lc1Out, "%d\n", siDF);
 
	// 結果表示
#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, lc1Out)) {
		siRes = -1;
	}
#else
	printf("%s", lc1Out);
#endif
 
	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpT);
	fclose(szpFpA);
#endif
 
	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", piTNo);
	}
	else {
		printf("NG %d\n", piTNo);
	}
#endif
 
	return 0;
}
 
int
main()
{
 
#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		fMain(i);
	}
#else
	fMain(0);
#endif
 
	return 0;
}