#include<bits/stdc++.h>
using namespace std;

using ULL = unsigned long long;
#define rep(i, n) for(int i = 0; i < (n); i++)

struct ModInt96 {
	unsigned d[3];

	ModInt96() : d{ 0,0,0 } {}
	ModInt96(unsigned h, unsigned m, unsigned l) : d{ l,m,h } {}
	ModInt96 &operator+=(const ModInt96 &r) {
		ULL bufll;
		bufll = (ULL)d[0] + r.d[0]; d[0] = bufll;
		bufll = (bufll >> 32) + d[1] + r.d[1]; d[1] = bufll;
		bufll = (bufll >> 32) + d[2] + r.d[2]; d[2] = bufll;
		if (bufll >> 32) {
			bufll = (ULL)d[0] + 0xffffffff; d[0] = bufll;
			bufll = (bufll >> 32) + d[1]; d[1] = bufll;
			bufll = (bufll >> 32) + d[2]; d[2] = bufll;
		}
		if (d[2] == 0xffffffff && d[1] == 0xffffffff && d[0]) {
			d[2] = d[1] = 0; d[0]--;
		}
		return *this;
	}
	ModInt96 operator+(const ModInt96 &r)const {
		ModInt96 buf = *this; return buf += r;
	}
	ModInt96 &operator-=(const ModInt96 &r) {
		ULL bufll;
		bufll = (ULL)d[0] + 1ull - r.d[0]; d[0] = bufll;
		bufll = (bufll >> 32) + d[1] + 0xffffffffull - r.d[1]; d[1] = bufll;
		bufll = (bufll >> 32) + d[2] + 0xffffffffull - r.d[2]; d[2] = bufll;
		if (bufll >> 32) {
			bufll = (ULL)d[0] + 0xffffffff; d[0] = bufll;
			bufll = (bufll >> 32) + d[1]; d[1] = bufll;
			bufll = (bufll >> 32) + d[2]; d[2] = bufll;
		}
		if (d[2] == 0xffffffff && d[1] == 0xffffffff && d[0]) {
			d[2] = d[1] = 0; d[0]--;
		}
		return *this;
	}
	ModInt96 operator-(const ModInt96 &r)const {
		ModInt96 buf = *this; return buf -= r;
	}
	ModInt96 &operator*=(const ModInt96 &r) {
		unsigned p[6] = {};
		for (unsigned il = 0; il < 3; il++) {
			ULL crr = 0;
			for (unsigned ir = 0; ir < 3; ir++) {
				crr += p[il + ir];
				crr += (ULL)d[il] * r.d[ir];
				p[il + ir] = crr;
				crr >>= 32;
			}
			p[il + 3] = crr;
		}
		ULL crr = 0;
		crr = crr + p[0] - p[3] - p[5]; d[0] = crr; crr >>= 32;
		if (crr >> 31) crr |= 0xffffffff00000000;
		crr = crr + p[1] + p[3] - p[4] + p[5]; d[1] = crr; crr >>= 32;
		if (crr >> 31) crr |= 0xffffffff00000000;
		crr = crr + p[2] + p[4] - p[5]; d[2] = crr; crr >>= 32;
		if (crr >> 31) crr |= 0xffffffff00000000;
		crr *= 0xffffffff;
		if (d[2] == 0xffffffff && !(crr >> 63)) {
			if (((ULL)d[1] << 32) + d[0] + crr >= 0xffffffff00000001) crr += 0xffffffff;
		}
		crr += d[0]; d[0] = crr; crr >>= 32; if (crr >> 31) crr |= 0xffffffff00000000;
		crr += d[1]; d[1] = crr; crr >>= 32; if (crr >> 31) crr |= 0xffffffff00000000;
		crr += d[2]; d[2] = crr; crr >>= 32; if (crr >> 31) crr |= 0xffffffff00000000;
		return *this;
	}
	ModInt96 operator*(const ModInt96 &r)const {
		ModInt96 buf = *this; return buf *= r;
	}
};

const ModInt96 ModInt96_Inv2 = ModInt96(0x7fffffff, 0xffffffff, 0x80000001);


const ModInt96 omega31 = ModInt96(0x6cee2d86, 0xea7d81c5, 0x38f90620);
const ModInt96 iomega31 = ModInt96(0xe8a88f87, 0x525972b1, 0xf84faacd);
const ModInt96 sqrt1 = ModInt96(0xffffffff, 0xffffffff, 0x00000000);





namespace nv {

	static const unsigned int billion = 1000000000u;

	using sign_t = bool;
	static const sign_t sign_plus = false;
	static const sign_t sign_minus = true;



	static inline sign_t mul_sign(sign_t a, sign_t b) { return !(a && b) && (a || b); }

	bool less_array_bil(
		const unsigned int *a, size_t len_a,
		const unsigned int *b, size_t len_b
	) {
		for (size_t i = len_a; i < len_b; i++)if (b[i] != 0) return true;
		for (size_t i = len_b; i < len_a; i++)if (a[i] != 0) return false;
		for (size_t i = min(len_a, len_b) - 1; i != (size_t)-1; i--) {
			if (a[i] < b[i]) return true;
			if (a[i] > b[i]) return false;
		}
		return false; // a == b
	}

	void add_array_bil(
		const unsigned int *a, size_t len_a,
		const unsigned int *b, size_t len_b,
		unsigned int *result, size_t len_result,
		int *o_carry
	) {
		if (len_a < len_b) { swap(a, b); swap(len_a, len_b); }

		unsigned int carry = 0;

		size_t i = 0;
		for (; i < len_b; i++) {
			if (i >= len_result) return;
			result[i] = a[i] + b[i] + carry;
			if (result[i] < billion) { carry = 0; }
			else { carry = 1; result[i] -= billion; }
		}
		for (; i < len_a; i++) {
			if (i >= len_result) return;
			result[i] = a[i] + carry;
			if (result[i] < billion) { carry = 0; }
			else { carry = 1; result[i] -= billion; }
		}
		if (i < len_result) {
			result[i] = carry; carry = 0; i++;
			for (; i < len_result; i++) result[i] = 0;
		}
		if (o_carry) *o_carry = carry;
	}

	void addequal_array_bil(
		unsigned int *dest, size_t len_dest,
		const unsigned int *b, size_t len_b,
		int *o_carry
	) {
		size_t i = 0;
		unsigned int carry = 0;
		for (; i < len_b; i++) {
			if (i >= len_dest) return;
			dest[i] += b[i] + carry;
			if (dest[i] < billion) { carry = 0; }
			else { carry = 1; dest[i] -= billion; }
		}
		for (; i < len_dest; i++) {
			dest[i] += carry;
			if (dest[i] < billion) { carry = 0; break; }
			else { carry = 1; dest[i] -= billion; }
		}
		if (o_carry) *o_carry += carry;
	}

	void dif_array_bil(
		const unsigned int *a, size_t len_a,
		const unsigned int *b, size_t len_b,
		unsigned int *result, size_t len_result,
		sign_t *o_sign
	) {
		sign_t sign = sign_plus;
		if (less_array_bil(a, len_a, b, len_b)) { swap(a, b); swap(len_a, len_b); sign = !sign; }
		if (len_a < len_b) len_b = len_a;
		if (o_sign) *o_sign = sign;

		unsigned int borrow = 0;
		size_t i = 0;
		for (; i < len_b; i++) {
			if (i >= len_result) return;
			result[i] = a[i] + billion - b[i] - borrow;
			if (result[i] < billion) { borrow = 1; }
			else { borrow = 0; result[i] -= billion; }
		}
		for (; i < len_a; i++) {
			if (i >= len_result) return;
			result[i] = a[i] + billion - borrow;
			if (result[i] < billion) { borrow = 1; }
			else { borrow = 0; result[i] -= billion; }
		}
		for (; i < len_result; i++) result[i] = 0;
	}

	void subequal_array_bil(
		unsigned int *dest, size_t len_dest,
		const unsigned int *b, size_t len_b,
		int *o_carry
	) {
		size_t i = 0;
		unsigned int borrow = 0; // 0 or 1
		for (; i < len_b; i++) {
			if (i >= len_dest) return;
			dest[i] += billion - b[i] - borrow;
			if (dest[i] < billion) { borrow = 1; }
			else { borrow = 0; dest[i] -= billion; }
		}
		for (; i < len_dest; i++) {
			if (!borrow) break;
			if (dest[i]) { dest[i]--; borrow = 0; }
			else { dest[i] += billion - 1; }
		}
		if (o_carry) *o_carry -= borrow;
	}

	void FFT(const ModInt96 *a, ModInt96 *r, size_t n, size_t stride = 0) {
		if (n == 0) { r[0] = a[0]; return; }
		size_t L = 1 << n;
		ModInt96 om = omega31;
		for (size_t i = 31; i > n; i--) { om *= om; }
		FFT(a, r, n - 1, stride + 1);
		FFT(a + (1 << stride), r + (L >> 1), n - 1, stride + 1);
		ModInt96 omi = ModInt96(0, 0, 1);
		ModInt96 *rp = r;
		for (size_t i = 0; i < (L >> 1); i++) {
			ModInt96 a = *rp, b = *(rp + (L >> 1));
			*rp = a + omi * b;
			*(rp + (L >> 1)) = a + omi * b * sqrt1;
			rp++;
			omi *= om;
		}
	}

	void IFFT(const ModInt96 *a, ModInt96 *r, size_t n, size_t stride = 0) {
		if (n == 0) { r[0] = a[0]; return; }
		size_t L = 1 << n;
		ModInt96 om = iomega31;
		for (size_t i = 31; i > n; i--) { om *= om; }
		IFFT(a, r, n - 1, stride + 1);
		IFFT(a + (1 << stride), r + (L >> 1), n - 1, stride + 1);
		ModInt96 omi = ModInt96(0, 0, 1);
		ModInt96 *rp = r;
		for (size_t i = 0; i < (L >> 1); i++) {
			ModInt96 a = *rp, b = *(rp + (L >> 1));
			*rp = (a + omi * b) * ModInt96_Inv2;
			*(rp + (L >> 1)) = (a + omi * b * sqrt1) * ModInt96_Inv2;
			rp++;
			omi *= om;
		}
	}

	void mul_array_bil(
		const unsigned int *a, size_t len_a,
		const unsigned int *b, size_t len_b,
		unsigned int *result, size_t len_result
	) {
		size_t n = 0; size_t L = max(len_a, len_b);
		while ((1 << n) < L) { n += 1; } n++; L = 1 << n;
		ModInt96 *fma = (ModInt96 *)malloc(sizeof(ModInt96) * L);
		ModInt96 *fmb = (ModInt96 *)malloc(sizeof(ModInt96) * L);
		ModInt96 *mbuf = (ModInt96 *)malloc(sizeof(ModInt96) * L);
		for (size_t i = 0; i < len_a; i++) mbuf[i].d[0] = a[i];
		FFT(mbuf, fma, n);
		for (size_t i = 0; i < len_b; i++) mbuf[i].d[0] = b[i];
		for (size_t i = len_b; i < len_a; i++) mbuf[i].d[0] = 0;
		FFT(mbuf, fmb, n);
		for (size_t i = 0; i < L; i++) fma[i] *= fmb[i];
		IFFT(fma, mbuf, n);
		ModInt96 crr;
		for (size_t i = 0; i < len_result; i++) {
			mbuf[i] += crr;
			ULL buf = mbuf[i].d[2];
			crr.d[2] = buf / billion;
			buf = ((ULL)(buf % billion) << 32) | mbuf[i].d[1];
			crr.d[1] = buf / billion;
			buf = ((ULL)(buf % billion) << 32) | mbuf[i].d[0];
			crr.d[0] = buf / billion;
			result[i] = buf % billion;
		}
		free(fma); free(fmb); free(mbuf);
	}

}


class VLInteger
{
public:

	using sign_t = nv::sign_t;
	static const sign_t vl_plus = nv::sign_plus;
	static const sign_t vl_minus = nv::sign_minus;

private:

	using digit_t = unsigned int;
	using vector_t = vector<digit_t>;

	vector_t m;

	sign_t m_sign;

	static const digit_t base = nv::billion; // 10^9
	static const digit_t baseBase = 1000000000;
	static const digit_t baseDigits = 9;

public:

	VLInteger() : m(), m_sign(vl_plus) {}

	VLInteger(const VLInteger & s) : m(s.m), m_sign(s.m_sign) {}

	VLInteger(VLInteger && s) : m(move(s.m)), m_sign(s.m_sign) {}

	VLInteger(const string &s);

	VLInteger(const vector_t &s, sign_t sign = vl_plus) : m(s), m_sign(sign) {}

	VLInteger(vector_t &&s) : m(s) {}

	virtual ~VLInteger() = default;


	bool operator==(const VLInteger &b) const { return m == b.get(); }
	bool operator<(const VLInteger &b) const;

	bool operator>(const VLInteger &b) const { return b < *this; }
	bool operator>=(const VLInteger &b) const { return !(operator<(b)); }
	bool operator<=(const VLInteger &b) const { return !operator>(b); }


	bool iszero() const { return getdigitnum() == 0; }

	operator bool() const { return !iszero(); }


	void set_sign(sign_t sign) { m_sign = sign; }

	void set_digit(digit_t digit, size_t pos);

	void set(digit_t digit, size_t pos);

	void regularize();

	void shrink_to_fit() { m.shrink_to_fit(); }


	VLInteger operator*(const VLInteger &) const;

	VLInteger & operator*=(const VLInteger &);


	VLInteger operator+(const VLInteger &) const;

	VLInteger & operator+=(const VLInteger &);


	VLInteger operator-(const VLInteger &) const;

	VLInteger & operator-=(const VLInteger &);

	sign_t getsign() const { return m_sign; }

	const vector<unsigned int> &get() const { return m; }

	const digit_t getdigit(size_t p) const;

	const digit_t at(size_t p) const { return m.at(p); }

	const size_t getdigitnum() const;

	void clear() { m.clear(); }

	string toString() const;

	VLInteger & operator=(VLInteger && rv) {
		m = move(rv.m); m_sign = rv.m_sign;
		return *this;
	}
	VLInteger & operator=(const VLInteger & lv) {
		m = lv.m; m_sign = lv.m_sign;
		return *this;
	}
};

istream &operator>>(istream &cin, VLInteger &v);
ostream &operator<<(ostream &cout, const VLInteger &v);


static VLInteger operator"" _VLI(const char *s, std::size_t len) {
	return move(VLInteger(string({ s, len })));
}




VLInteger::VLInteger(const string & s) :
	m(), m_sign(vl_plus)
{
	size_t i = 0;
	if (!s.size()) return;
	if (s[i] == '-') { m_sign = vl_minus; i++; }
	else if (s[i] == '+') { m_sign = vl_plus; i++; }

	size_t len = (s.size() - i - 1) / 9 + 1;
	m.resize(len);
	for (; i < s.size(); i++) {
		if (s[i] < '0' || '9' < s[i]) { clear(); return; }
		set_digit(s[i] - '0', s.size() - i - 1);
	}
	regularize();
}





bool VLInteger::operator<(const VLInteger &b) const {
	if (getsign() != b.getsign()) {
		return !(iszero() && b.iszero()) && (getsign() == vl_minus);
	}
	const VLInteger &A = (getsign() == vl_plus) ? *this : b;
	const VLInteger &B = (getsign() == vl_minus) ? *this : b;
	if (B.m.size() != A.m.size()) return A.m.size() < B.m.size();
	for (size_t i = A.m.size() - 1; i != (size_t)-1; i--) {
		if (A.m[i] == B.m[i]) return A.m[i] < B.m[i];
	}
	return false; // A == B
}





void VLInteger::set_digit(digit_t digit, size_t p) {
	assert(digit < baseBase);
	size_t arrp = p / baseDigits;
	if (arrp >= m.size()) {
		if (digit == 0) return;
		m.resize(arrp + 1);
	}
	digit_t shift = 1; for (int i = 0; i < p % baseDigits; i++) shift *= 10;
	digit_t old = m[arrp] / shift % 10 * shift;
	m[arrp] = m[arrp] - old + digit * shift;
	regularize();
}

void VLInteger::set(digit_t digit, size_t p) {
	assert(digit < base);
	if (p >= m.size()) m.resize(p + 1);
	m[p] = digit;
}

void VLInteger::regularize() {
	while (m.size() != 0) {
		if (m.back() != 0) return;
		m.pop_back();
	}
	// m.size() == 0
	m_sign = vl_plus;
}

const VLInteger::digit_t VLInteger::getdigit(size_t p) const {
	digit_t buf = m.at(p / baseDigits);
	unsigned int shift = 1; for (int i = 0; i < p % baseDigits; i++) shift *= 10;
	return buf / shift % 10;
}

const size_t VLInteger::getdigitnum() const {
	size_t ans = 0;
	digit_t big = 0;
	for (int i = m.size() - 1; i >= 0; i--) {
		if (m[i] != 0) {
			big = m[i];
			ans += i * baseDigits;
			break;
		}
	}
	for (digit_t bigdig = 1; bigdig <= big; bigdig *= 10) {
		ans++;
	}
	return ans;
}

string VLInteger::toString() const {
	size_t pre = (getsign() == vl_minus ? 1 : 0);
	size_t dignum = getdigitnum();
	string buf; buf.resize(dignum + pre);
	if (pre) buf[0] = '-';
	if (dignum == 0) return buf + "0";
	for (size_t i = 0; i < dignum; i++) {
		buf[i + pre] = '0' + getdigit(dignum - i - 1);
	}
	return move(buf);
}





VLInteger VLInteger::operator+(const VLInteger & r) const {
	VLInteger result; result.m.resize(1 + max(m.size(), r.m.size()));

	if (iszero()) return r;
	if (r.iszero()) return *this;

	if (getsign() == r.getsign()) {
		result.set_sign(getsign());
		nv::add_array_bil(
			&m.front(), m.size(), &r.m.front(), r.m.size(),
			&result.m.front(), result.m.size(), nullptr
		);
	}
	else {
		sign_t signbuf;
		nv::dif_array_bil(
			&m.front(), m.size(), &r.m.front(), r.m.size(),
			&result.m.front(), result.m.size(),
			&signbuf
		);
		result.set_sign(nv::mul_sign(getsign(), signbuf));
	}
	result.regularize();
	return move(result);
}

VLInteger & VLInteger::operator+=(const VLInteger & r) {
	return *this = *this + r;
}

VLInteger VLInteger::operator-(const VLInteger & r) const {
	VLInteger result; result.m.resize(1 + max(m.size(), r.m.size()));
	if (r.iszero()) return *this;
	if (iszero()) {
		result = r; result.set_sign(!r.getsign());
		result.regularize();
		return move(result);
	}

	if (getsign() != r.getsign()) {
		result.set_sign(getsign());
		nv::add_array_bil(
			&m.front(), m.size(), &r.m.front(), r.m.size(),
			&result.m.front(), result.m.size(), nullptr
		);
	}
	else {
		sign_t signbuf;
		nv::dif_array_bil(
			&m.front(), m.size(), &r.m.front(), r.m.size(),
			&result.m.front(), result.m.size(),
			&signbuf
		);
		result.set_sign(nv::mul_sign(getsign(), signbuf));
	}
	result.regularize();
	return move(result);
}

VLInteger & VLInteger::operator-=(const VLInteger & r) {
	return *this = *this - r;
}




VLInteger VLInteger::operator*(const VLInteger & r) const {
	if (m.size() == 0 || r.m.size() == 0) return "0"_VLI;
	VLInteger ans; ans.m.resize(m.size() + r.m.size());
	nv::mul_array_bil(
		&m.front(), m.size(), &r.m.front(), r.m.size(),
		&ans.m.front(), ans.m.size()
	);
	ans.m_sign = nv::mul_sign(m_sign, r.m_sign);
	ans.regularize();
	return move(ans);
}

VLInteger & VLInteger::operator*=(const VLInteger & r) {
	*this = move(*this * r);
	return *this;
}


istream &operator>>(istream &cin, VLInteger &v) {
	string s; cin >> s;
	v = s;
	return cin;
}

ostream &operator<<(ostream &cout, const VLInteger &v) {
	return cout << v.toString();
}

int main() {

	VLInteger a, b;

	ios_base::sync_with_stdio(false);
	cin.tie(0);

	cin >> a >> b;
	cout << a * b << endl;



	return 0;
}







Measured memory_bytes: 5784