Problem:
Score : 2000 points

Problem Statement

Snuke has R red balls and B blue balls.
He distributes them into K boxes, so that no box is empty and no two boxes are identical.
Compute the maximum possible value of K.

Formally speaking, let's number the boxes 1 through K.
If Box i contains r_i red balls and b_i blue balls, the following conditions must be satisfied:

For each i (1 \leq i \leq K), r_i > 0 or b_i > 0.

For each i, j (1 \leq i < j \leq K), r_i \neq r_j or b_i \neq b_j.

\sum r_i = R and \sum b_i = B (no balls can be left outside the boxes).

Constraints

1 \leq R, B \leq 10^{9}

Input

Input is given from Standard Input in the following format:

R B

Output

Print the maximum possible value of K.

Sample Input 1

8 3

Sample Output 1

5

The following picture shows one possible way to achieve K = 5:

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

//#define NDEBUG
#include <cstddef>
#include <cstdint>
#include <vector>

using i8 = ::std::int_least8_t;
using i32 = ::std::int_least32_t;
using i64 = ::std::int_least64_t;
using u8 = ::std::uint_least8_t;
using u32 = ::std::uint_least32_t;
using u64 = ::std::int_least64_t;
using isize = ::std::ptrdiff_t;
using usize = ::std::size_t;

template <class T = usize> class rep {
	const T f, l;

public:
	class itr {
		friend rep;
		T i;
		constexpr itr(T x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		constexpr T operator*() const noexcept { return i; }
		constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
	};
	constexpr rep(const T first, const T last) noexcept : f(first), l(last) {}
	constexpr itr begin() const noexcept { return itr(f); }
	constexpr itr end() const noexcept { return itr(l); }
};
template <class T = usize> class revrep {
	const T f, l;

public:
	class itr {
		friend revrep;
		T i;
		constexpr itr(T x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		constexpr T operator*() const noexcept { return i; }
		constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
	};
	constexpr revrep(const T first, const T last) noexcept : f(first), l(last) {}
	constexpr itr begin() const noexcept { return itr(l - 1); }
	constexpr itr end() const noexcept { return itr(f - 1); }
};
template <class T> bool amax(T &a, const T &b) {
	return a <= b ? (a = b, 1) : 0;
}
template <class T> bool amin(T &a, const T &b) {
	return b <= a ? (a = b, 1) : 0;
}
template <class T> bool asmax(T &a, const T &b) {
	return b <= a ? 0 : (a = b, 1);
}
template <class T> bool asmin(T &a, const T &b) {
	return a <= b ? 0 : (a = b, 1);
}
template <class T> using vec_alias = ::std::vector<T>;
template <class T> auto md_vec(usize n, const T &value) {
	return ::std::vector<T>(n, value);
}
template <class... Args> auto md_vec(usize n, Args... args) {
	return ::std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
}
template <class T> const T &as_const(const T &v) noexcept { return v; }
template <class T> constexpr T difference(const T &a, const T &b) {
	return a <= b ? b - a : a - b;
}

#include <algorithm>
#include <iostream>
#include <utility>
#include<numeric>
#include<cassert>
#include<tuple>


static constexpr u64 P = 10000000019ULL;

u64 count_points(const u64 p, const u64 z) {
	const u64 q = P - p;
	u64 ret = 0;
	if (p < q) {
		for (u64 y = 0;z >= q*y;++y) {
			ret += (z - q*y) / p + 1;
		}
	}
	else {
		for (u64 x = 0;z >= p*x;++x) {
			ret += (z - p*x) / q + 1;
		}
	}
	return ret;
}

::std::pair<u64, u64> calc_sum(const u64 p, const u64 z, u64 cnt) {
	const u64 q = P - p;
	u64 X = 0, Y = 0;
	if (p < q) {
		for (u64 y = 0;z >= q*y;++y) {
			const u64 d = (z - q*y) / p;
			Y += y*(d + 1);
			X += d*(d + 1) / 2;
			if (cnt != 0 && (z + 1 - q*y) % p == 0) {
				Y += y;
				X += d + 1;
				--cnt;
			}
		}
	}
	else {
		for (u64 x = 0;z >= p*x;++x) {
			const u64 d = (z - p*x) / q;
			X += x*(d + 1);
			Y += d*(d + 1) / 2;
			if (cnt != 0 && (z + 1 - p*x) % q == 0) {
				X += x;
				Y += d + 1;
				--cnt;
			}
		}
	}
	return ::std::make_pair(X, Y);
}

u64 calc_z(const u64 p, const u64 k) {
	u64 z_le = 0, z_gt = P * 3000;
	while (z_gt - z_le != 1) {
		u64 z = (z_le + z_gt) / 2;
		if (count_points(p, z) <= k) {
			z_le = z;
		}
		else {
			z_gt = z;
		}
	}
	return z_le;
}

bool check_k(const u64 R, const u64 B, const u64 k) {
	u64 p_lower = 0, p_upper = P;
	while (p_upper - p_lower != 1) {
		u64 p = (p_lower + p_upper) / 2;
		u64 z = calc_z(p, k);
		u64 cnt = k - count_points(p, z);
		u64 X, Y;
		::std::tie(X, Y) = calc_sum(p, z, cnt);
		if (X <= R) {
			if (Y <= B) {
				return true;
			}
			else {
				p_upper = p;
			}
		}
		else {
			if (Y <= B) {
				p_lower = p;
			}
			else {
				return false;
			}
		}
	}
	u64 z1 = calc_z(p_upper, k);
	u64 z2 = calc_z(p_lower, k);
	u64 X1, X2, Y1, Y2;
	::std::tie(X1, Y1) = calc_sum(p_upper, z1,
		k - count_points(p_upper, z1));
	::std::tie(X2, Y2) = calc_sum(p_lower, z2,
		k - count_points(p_lower, z2));
	if ((X2 - X1)*(B - Y1) >= (Y2 - Y1)*(R - X1)) {
		return true;
	}
	else {
		return false;
	}
}

int main() {
	u64 R, B;
	::std::cin >> R >> B;

	u64 k_ok = 0, k_ng = 4000000;
	while (k_ng - k_ok != 1) {
		u64 k = (k_ok + k_ng) / 2;
		if (check_k(R, B, k)) {
			k_ok = k;
		}
		else {
			k_ng = k;
		}
	}

	::std::cout << k_ok - 1 << ::std::endl;
	return 0;
}