#include <iostream>
#include <iomanip>
#include <vector>
#include <type_traits>
#include <cmath>
#include <complex>
#include <cassert>

constexpr double pi = std::acos(-1);
using i64 = int_fast64_t;
using u64 = uint_fast64_t;
using i32 = int_fast32_t;
using u32 = uint_fast32_t;

class FFT {
public:
	static std::vector<std::complex<double>> fft(std::vector<std::complex<double>> &f) {
		u32 n = f.size();
		if(n <= 1) return f;
	 
		std::vector<std::complex<double>> res = f;
		
		// Bit rev
		u32 s = 0;
		while((u32)(1 << s) < n) s++;
		for(u32 i = 0; i < n; i++) {
			u32 j = 0;
			for(u32 k = 0; k < s; k++) j |= (i >> k & 1) << (s - 1 - k);
			if(i < j) std::swap(res[i], res[j]);
		}
	 
		double ang = -1.0 * pi / (2.0 * n);
		std::complex<double> zeta1, zeta3, x0, x1, x3;
		u32 m, mm, rev, k1, k2, k3;
	 
		for(m = 4; m <= n; m <<= 1) {
			mm = m >> 2;
			for(u32 j = mm; j >= 1; j >>= 2) {
				for(u32 k = mm - j; k < mm - (j >> 1); k++) {
					k1 = k + mm;
					k2 = k1 + mm;
					k3 = k2 + mm;
					x1 = res[k] - res[k1];
					res[k] += res[k1];
					x3 = res[k3] - res[k2];
					res[k2] += res[k3];
					res[k1] = std::complex<double>(x1.real() - x3.imag(), x1.imag() + x3.real());	//res[k1] = x1 + x3 * ui;
					res[k3] = std::complex<double>(x1.real() + x3.imag(), x1.imag() - x3.real());	// res[k3] = x1 - x3 * ui;
				}
			}
			if(m == n) continue;
	 
			rev = n >> 1;
			zeta1 = std::cos(ang * rev);
			for(u32 j = mm; j >= 1; j >>= 2) {
				for(u32 k = m + mm - j; k < m + mm - (j >> 1); k++) {
					k1 = k + mm;
					k2 = k1 + mm;
					k3 = k2 + mm;
					x1 = res[k] - res[k1];
					res[k] += res[k1];
					x3 = res[k3] - res[k2];
					res[k2] += res[k3];
					x0 = std::complex<double>(x1.real() - x3.imag(), x1.imag() + x3.real());	// x0 = x1 + x3 * ui; 
					x0 = std::complex<double>(x0.real() + x0.imag(), x0.imag() - x0.real());	// x0 *= 1.0 - ui;
					res[k1] = zeta1 * x0;
					x0 = std::complex<double>(x1.real() + x3.imag(), x1.imag() - x3.real());	// x0 = x1 - x3 * ui;
					x0 = std::complex<double>(-x0.real() + x0.imag(), -x0.imag() - x0.real());	// x0 *= -1.0 - ui;
					res[k3] = zeta1 * x0;
				}
			}
	 
			for(u32 i = 2 * m; i < n; i += m) {
				for(u32 j = n >> 1; j > (rev ^= j); j >>= 1);
				zeta1 = std::polar(1.0, ang * rev);
				zeta3 = std::polar(1.0, 3.0 * ang * rev);
				for(u32 j = mm; j >= 1; j >>= 2) {
					for(u32 k = i + mm - j; k < i + mm - (j >> 1); k++) {
						k1 = k + mm;
						k2 = k1 + mm;
						k3 = k2 + mm;
						x1 = res[k] - res[k1];
						res[k] += res[k1];
						x3 = res[k3] - res[k2];
						res[k2] += res[k3];
						x0 = std::complex<double>(x1.real() - x3.imag(), x1.imag() + x3.real()); // x0 = x1 + x3 * ui;
						res[k1] = zeta1 * x0;
						x0 = std::complex<double>(x1.real() + x3.imag(), x1.imag() - x3.real()); // x0 = x1 - x3 * ui;
						res[k3] = zeta3 * x0;
					}
				}
			}
		}
	 
		mm = n >> 1;
		for(u32 j = mm; j >= 1; j >>= 2) {
			for(u32 k = mm - j; k < mm - (j >> 1); k++) {
				k1 = mm + k;
				x0 = res[k] - res[k1];
				res[k] += res[k1];
				res[k1] = x0;
			}
		}
	 
		return res;
	}
	static std::vector<std::complex<double>> ifft(std::vector<std::complex<double>> &f) {
		u32 n = f.size();
		if(n <= 1) return f;
	 
		std::vector<std::complex<double>> res = f;
		
		// Bit rev
		u32 s = 0;
		while((u32)(1 << s) < n) s++;
		for(u32 i = 0; i < n; i++) {
			u32 j = 0;
			for(u32 k = 0; k < s; k++) j |= (i >> k & 1) << (s - 1 - k);
			if(i < j) std::swap(res[i], res[j]);
		}
	 
		double ang = 1.0 * pi / (2.0 * n);
		std::complex<double> zeta1, zeta3, x0, x1, x3;
		u32 m, mm, rev, k1, k2, k3;
	 
		for(m = 4; m <= n; m <<= 1) {
			mm = m >> 2;
			for(u32 j = mm; j >= 1; j >>= 2) {
				for(u32 k = mm - j; k < mm - (j >> 1); k++) {
					k1 = k + mm;
					k2 = k1 + mm;
					k3 = k2 + mm;
					x1 = res[k] - res[k1];
					res[k] += res[k1];
					x3 = res[k3] - res[k2];
					res[k2] += res[k3];
					res[k1] = std::complex<double>(x1.real() + x3.imag(), x1.imag() - x3.real());	// res[k1] = x1 - x3 * ui;
					res[k3] = std::complex<double>(x1.real() - x3.imag(), x1.imag() + x3.real());	// res[k3] = x1 + x3 * ui;
				}
			}
			if(m == n) continue;
	 
			rev = n >> 1;
			zeta1 = std::cos(ang * rev);
			for(u32 j = mm; j >= 1; j >>= 2) {
				for(u32 k = m + mm - j; k < m + mm - (j >> 1); k++) {
					k1 = k + mm;
					k2 = k1 + mm;
					k3 = k2 + mm;
					x1 = res[k] - res[k1];
					res[k] += res[k1];
					x3 = res[k3] - res[k2];
					res[k2] += res[k3];
					x0 = std::complex<double>(x1.real() + x3.imag(), x1.imag() - x3.real());	// x0 = x1 - x3 * ui;
					x0 = std::complex<double>(x0.real() - x0.imag(), x0.imag() + x0.real());	// x0 *= 1.0 + ui;
					res[k1] = zeta1 * x0;
					x0 = std::complex<double>(x1.real() - x3.imag(), x1.imag() + x3.real());	// x0 = x1 + x3 * ui;
					x0 = std::complex<double>(-x0.real() - x0.imag(), x0.real() + x0.imag());	// x0 *= -1.0 + ui;
					res[k3] = zeta1 * x0;
				}
			}
	 
			for(u32 i = 2 * m; i < n; i += m) {
				for(u32 j = n >> 1; j > (rev ^= j); j >>= 1);
				zeta1 = std::polar(1.0, ang * rev);
				zeta3 = std::polar(1.0, 3.0 * ang * rev);
				for(u32 j = mm; j >= 1; j >>= 2) {
					for(u32 k = i + mm - j; k < i + mm - (j >> 1); k++) {
						k1 = k + mm;
						k2 = k1 + mm;
						k3 = k2 + mm;
						x1 = res[k] - res[k1];
						res[k] += res[k1];
						x3 = res[k3] - res[k2];
						res[k2] += res[k3];
						x0 = std::complex<double>(x1.real() + x3.imag(), x1.imag() - x3.real());	// x0 = x1 - x3 * ui;
						res[k1] = zeta1 * x0;
						x0 = std::complex<double>(x1.real() - x3.imag(), x1.imag() + x3.real());	// x0 = x1 + x3 * ui;
						res[k3] = zeta3 * x0;
					}
				}
			}
		}
	 
		mm = n >> 1;
		for(u32 j = mm; j >= 1; j >>= 2) {
			for(u32 k = mm - j; k < mm - (j >> 1); k++) {
				k1 = k + mm;
				x0 = res[k] - res[k1];
				res[k] += res[k1];
				res[k1] = x0;
			}
		}
	 
		return res;
	}
};

// number of base digits
constexpr u64 MAX_DIGITNUM = 6;
// radix base
constexpr u64 RADIX_BASE = 10;
// radix
constexpr u64 RADIX = std::pow(RADIX_BASE, MAX_DIGITNUM);

// sign
using SIGN = bool;
constexpr bool PLUS = true;
constexpr bool MINUS = false;

using DIGITS = std::vector<u64>;

class BigInt {
private:
	// 12345678 => digits = {78, 56, 34, 12}
	DIGITS digits;
	SIGN sign;

	void to_zero() noexcept;
	void to_radix_power(u64 n) noexcept;
	void push_up(u64 num) noexcept;	// link as upper digit

	// unsigned operations	
	// absolute peer arithmetics
	// The argument does not have to be non-negative.
	void add(const BigInt &x) noexcept;	
	SIGN sub(const BigInt &x) noexcept;	// automatically subtracted from the larger one
	void mul(const BigInt &x) noexcept;	
	void div_short(const BigInt &x) noexcept;
	void div(const BigInt &x) noexcept;
	bool is_equal(const BigInt &x) const noexcept;	
	bool less_than(const BigInt &x, bool equal = false) const noexcept;	
	bool greater_than(const BigInt &x, bool equal = false) const noexcept;

	// absolute
	BigInt abs() const noexcept;

	// signed operations (arithmetic)
	void a_add(const BigInt &x) noexcept;	
	void a_sub(const BigInt &x) noexcept; 
	void a_mul(const BigInt &x) noexcept;	
	void a_div(const BigInt &x) noexcept;
	bool a_is_equal(const BigInt &x) const noexcept;	
	bool a_less_than(const BigInt &x, bool equal = false) const noexcept;	
	bool a_greater_than(const BigInt &x, bool equal = false) const noexcept;

	BigInt(const DIGITS &digits);
	
public:
	// default constructor
	BigInt();

	u64 at(i64 n) const noexcept;

	void resize(size_t size) noexcept;
	void normalize() noexcept;	// remove meaningless 0 from the top digit
	void align() noexcept;		// adjusted so that each digit does not exceed RADIX

	// integer constructor
	template<typename T, std::enable_if_t<std::is_integral<T>::value, std::nullptr_t> = nullptr>
	BigInt(T n): BigInt(std::to_string(n)) {
	}

	// std::string constructor
	BigInt(const std::string &x);

	size_t size() const noexcept;

	/* operators */
	// io
	friend std::ostream &operator <<(std::ostream &os, BigInt &x) noexcept {
		if(x.sign == MINUS && x != 0) os << "-";
		os << x.digits.at(x.size() - 1);
		for(size_t i = x.size() - 1; i --> 0;) os << std::setw(MAX_DIGITNUM) << std::setfill('0') << x.digits.at(i);
		return os;
	}

	friend std::ostream &operator <<(std::ostream &os, BigInt &&x) noexcept {
		if(x.sign == MINUS && x != 0) os << "-";
		os << x.digits.at(x.size() - 1);
		for(size_t i = x.size() - 1; i --> 0;) os << std::setw(MAX_DIGITNUM) << std::setfill('0') << x.digits.at(i);
		return os;
	}

	friend std::istream &operator >>(std::istream &is, BigInt &x) noexcept {
		std::string s;
		is >> s;
		x = BigInt(s);
		return is;
	}

	// arithmetic
	BigInt &operator +=(const BigInt &x) noexcept {
		a_add(x);
		return *this;
	}

	BigInt &operator -=(const BigInt &x) noexcept {
		a_sub(x);
		return *this;
	}

	BigInt &operator *=(const BigInt &x) noexcept {
		a_mul(x);
		return *this;
	}

	BigInt &operator /=(const BigInt &x) noexcept {
		a_div(x);
		return *this;
	}

	friend BigInt operator +(BigInt lhs, const BigInt &rhs) noexcept {
		lhs += rhs;
		return lhs;
	}

	friend BigInt operator -(BigInt lhs, const BigInt &rhs) noexcept {
		lhs -= rhs;
		return lhs;
	}

	friend BigInt operator *(BigInt lhs, const BigInt &rhs) noexcept {
		lhs *= rhs;
		return lhs;
	}

	friend BigInt operator /(BigInt lhs, const BigInt &rhs) noexcept {
		lhs /= rhs;
		return lhs;
	}

	// unary
	BigInt &operator ++() noexcept {
		operator +=(1);
		return *this;
	}

	BigInt operator ++(int) noexcept {
		BigInt x = *this;
		operator +=(1);
		return x; 
	}

	BigInt &operator --() noexcept {
		operator -=(1);
		return *this;
	}

	BigInt operator --(int) noexcept {
		BigInt x = *this;
		operator -=(1);
		return x;
	}

	BigInt operator +() const noexcept {
		return *this;
	}

	BigInt operator -() const noexcept {
		BigInt x = *this;
		x.sign = !x.sign;
		return x;
	}

	// comparison
	friend bool operator ==(const BigInt &lhs, const BigInt &rhs) noexcept {
		return lhs.a_is_equal(rhs);
	}

	friend bool operator !=(const BigInt &lhs, const BigInt &rhs) noexcept {
		return !lhs.a_is_equal(rhs);
	}

	friend bool operator <(const BigInt &lhs, const BigInt &rhs) noexcept {
		return lhs.a_less_than(rhs);
	}

	friend bool operator <=(const BigInt &lhs, const BigInt &rhs) noexcept {
		return lhs.a_less_than(rhs, true);
	}

	friend bool operator >(const BigInt &lhs, const BigInt &rhs) noexcept {
		return lhs.a_greater_than(rhs);
	}

	friend bool operator >=(const BigInt &lhs, const BigInt &rhs) noexcept {
		return lhs.a_greater_than(rhs, true);
	}
};

inline BigInt BigInt::abs() const noexcept {
	BigInt res = *this;
	res.sign = PLUS;
	return res;
}

inline void BigInt::resize(size_t size) noexcept {
	this->digits.resize(size, 0);
}

inline void BigInt::normalize() noexcept {
	while(size() > 0) {
		if(this->digits.back() == 0) this->digits.pop_back();
		else break;
	}

	if(size() == 0) to_zero();
}

inline u64 BigInt::at(i64 n) const noexcept {
	return this->digits.at(n);
}

inline void BigInt::to_zero() noexcept {
	std::vector<u64>().swap(this->digits);
	push_up(0);
}

inline void BigInt::to_radix_power(u64 n) noexcept {
	to_zero();
	if(n == 0) return;

	this->digits.reserve(n);
	for(u64 i = 0; i < n -1; i++) push_up(0);
	push_up(1);
}

inline void BigInt::push_up(u64 num) noexcept {
	this->digits.emplace_back(num);
}

inline size_t BigInt::size() const noexcept {
	return this->digits.size();
}

inline void BigInt::align() noexcept {
	for(size_t i = 0; i < this->digits.size() - 1; i++) {
		if(this->digits.at(i) >= RADIX) {
			this->digits.at(i + 1) += this->digits.at(i) / RADIX;
			this->digits.at(i) %= RADIX;
		}
	}

	if(this->digits.back() >= RADIX) {
		this->push_up(this->digits.back() / RADIX);
		this->digits.at(this->digits.size() - 2) %= RADIX;
	}
}


BigInt::BigInt(): BigInt("0") {
}

BigInt::BigInt(const DIGITS &digits) {
	this->sign = PLUS;
	this->digits = digits;
}

BigInt::BigInt(const std::string &x) {
	std::string num = x;

	this->sign = PLUS;
	if(num.size() != 0) {
		if(num.front() == '+') num.erase(num.begin());
		else if(num.front() == '-') {
			num.erase(num.begin());
			this->sign = MINUS;
		}
	}

	if(num.size() == 0) num = "0";

	while(num.size() > MAX_DIGITNUM) {
		push_up(std::stoull(num.substr(num.size() - MAX_DIGITNUM, MAX_DIGITNUM)));
		for(size_t i = 0; i < MAX_DIGITNUM; i++) num.pop_back();
	}
	push_up(std::stoull(num));
}

void BigInt::add(const BigInt &x) noexcept {
	if(x == 0) return;

	if(size() < x.size()) resize(x.size());

	u64 buf, carry = 0;
	u64 rd;
	for(size_t i = 0; i < size(); i++) {
		rd = (i < x.size())? x.digits.at(i) : 0;
		buf = this->digits.at(i) + rd + carry;
		carry = buf / RADIX;
		this->digits.at(i) = buf % RADIX;
	}

	if(carry != 0) push_up(carry);
	normalize();
}

SIGN BigInt::sub(const BigInt &x) noexcept {
	if(is_equal(x)) {
		to_zero();
		return PLUS;
	}

	u32 borrow = 0;
	u64 rd;

	// *this - x
	if(greater_than(x)) {
		for(size_t i = 0; i < size(); i++) {
			rd = (i < x.size())? x.digits.at(i) : 0;
			if(this->digits.at(i) >= rd + borrow) {
				this->digits.at(i) = this->digits.at(i) - borrow - rd;
				borrow = 0;
			} else {
				this->digits.at(i) = this->digits.at(i) + RADIX - borrow - rd;
				borrow = 1;
			}
		}
		normalize();
		return PLUS;
	}

	// x - *this
	if(size() < x.size()) resize(x.size());
	for(size_t i = 0; i < x.size(); i ++) {
		rd = (i < size())? this->digits.at(i) : 0;
		if(x.digits.at(i) >= rd + borrow) {
			this->digits.at(i) = x.digits.at(i) - borrow - rd;
			borrow = 0;
		} else {
			this->digits.at(i) = x.digits.at(i) + RADIX - borrow - rd;
			borrow = 1;
		}
	}
	normalize();
	return MINUS;
}

void BigInt::mul(const BigInt &x) noexcept {
	if(x == 0) {
		to_zero();
		return;
	}

	// adjust the number of digits to 2^n
	size_t n = 1;
	while (n < size() + x.size()) n <<= 1;

	std::vector<std::complex<double>> a(n);
	for(size_t i = 0; i < n; i++) {
		a.at(i).real((i >= size()) ? 0 : this->digits.at(i));
		a.at(i).imag((i >= x.size()) ? 0 : x.digits.at(i));
	}

	a = FFT::fft(a);
	std::vector<std::complex<double>> res(n);
	for(size_t i = 0; i < n; i++) {
		res.at(i) = (a.at(i) + std::conj(a.at((n - i) % n))) * 0.5 * (a.at(i) - std::conj(a.at((n - i) % n))) * std::complex<double>(0, -0.5);
	}
		
	res = FFT::ifft(res);
	resize(n);
	for(size_t i = 0; i < n; i++) this->digits.at(i) = std::round(res.at(i).real() / static_cast<double>(n));

	normalize();
	align();
}

// short divisor
void BigInt::div_short(const BigInt &x) noexcept {
	if(x.abs() < RADIX) {
		u64 dividend = this->digits.back();
		for(u64 i = this->digits.size(); i --> 0;) {
			this->digits.at(i) = dividend / x.at(0);
			if(i == 0) {
				normalize();
				return;
			}
			dividend = (dividend % x.at(0)) * RADIX + this->digits.at(i - 1);
		}
	}
	
	u64 radix_per_10 = RADIX / 10;
	BigInt dividend(this->digits.back() / radix_per_10);

	u64 qq, xx;
	BigInt rr;
	for(u64 i = this->digits.size(); i --> 0;) {
		xx = 0;
		for(u64 j = MAX_DIGITNUM; j --> 0;) {
			qq = 0;
			rr = dividend;
			while(rr >= x.abs()) {
				rr -= x.abs();
				qq++;
			}
			xx += qq * std::pow(RADIX_BASE, j);
			
			if(i == 0 && j == 0) {
				this->digits.at(i) = xx;
				normalize();
				return;
			}
			
			if(qq != 0) dividend = rr;
			dividend *= RADIX_BASE;
			if(j == 0) dividend += at(i - 1) / radix_per_10;
			else dividend += at(i) / static_cast<u64>(std::pow(RADIX_BASE, j - 1)) % 10;
		}
		this->digits.at(i) = xx;
	}
}


// Knuth D
void BigInt::div(const BigInt &x) noexcept {
	assert(x != 0);
	if(abs() < x.abs()) {
		to_zero();
		return;
	}

	if(abs() == x.abs()) {
		SIGN si = this->sign;
		to_zero();
		operator++();
		this->sign = si;
		return;
	}

	i64 s, t;
	s = size() - 1, t = x.size() - 1;
	if(t <= 1) {
		div_short(x);
		return;
	}

	u64 k = RADIX / (x.digits.back() + 1);
	BigInt a = abs() * k;
	BigInt b = x.abs() * k;

	DIGITS q(a.size(), 0);

	i64 u;
	u64 qp, rp;
	u64 fi = 1;
	while(true) {
		s = a.size() - 1 + fi;
		a.push_up(0);
		u = (a.at(s) < b.at(t))? s - t - 1 : s - t;
		qp = (a.at(s) * RADIX + a.at(s - 1)) / b.at(t);
		rp = (a.at(s) * RADIX + a.at(s - 1)) % b.at(t);
		while(rp < RADIX && qp * b.at(t - 1) > RADIX * rp + a.at(s - 2)) {
			qp--;
			rp += b.at(t);
		}

		q.at(u) = qp;
		BigInt xx;
		xx.to_radix_power(u);
		a -= b * qp * xx;
		if(a < 0) {
			--q.at(u);
			a += b * xx;
		}

		fi = 0;
		if(u == 0) {
			this->digits = q;
			normalize();
			return;
		}
	}
}

bool BigInt::is_equal(const BigInt &x) const noexcept {
	if(size() != x.size()) return false;

	for(size_t i = 0; i < size(); i++) {
		if(this->digits.at(i) != x.digits.at(i)) return false;
	}
	return true;
}

bool BigInt::less_than(const BigInt &x, bool equal) const noexcept {
	if(size() < x.size()) return true;
	if(size() > x.size()) return false;

	for(size_t i = size(); i --> 0;) {
		if(this->digits.at(i) < x.digits.at(i)) return true;
		if(this->digits.at(i) > x.digits.at(i)) return false;
	}

	// equal
	return equal;
}

bool BigInt::greater_than(const BigInt &x, bool equal) const noexcept {
	return !less_than(x, !equal);
}

void BigInt::a_add(const BigInt &x) noexcept {
	if(this->sign == x.sign) {
		add(x);
	} else {
		if(sub(x) == MINUS) this->sign = x.sign;
	}
}

void BigInt::a_sub(const BigInt &x) noexcept {
	a_add(-x);
}

void BigInt::a_mul(const BigInt &x) noexcept {
	mul(x);
	this->sign = !(this->sign ^ x.sign);
}

void BigInt::a_div(const BigInt &x) noexcept {
	div(x);
	this->sign = !(this->sign ^ x.sign);
}

bool BigInt::a_is_equal(const BigInt &x) const noexcept {
	if(is_equal(0) && x.is_equal(0)) return true;
	if(this->sign != x.sign) return false;
	return is_equal(x);
}

bool BigInt::a_less_than(const BigInt &x, bool equal) const noexcept {
	// +, - zero
	if(is_equal(0)) {
		if(x.sign == PLUS) return less_than(x, equal);
		else return greater_than(x, equal);
	}
	
	// different sign
	if(!x.is_equal(0)) {
		if(this->sign == MINUS && x.sign == PLUS) return true;
		if(this->sign == PLUS && x.sign == MINUS) return false;
	}

	// same sign
	if(this->sign == PLUS) return less_than(x, equal);
	return greater_than(x, equal);
}

bool BigInt::a_greater_than(const BigInt &x, bool equal) const noexcept {
	return !a_less_than(x, !equal);
}

int main() {
	BigInt x, y;
	std::cin >> x >> y;

	std::cout << x * y << std::endl;

	return 0;
}




Measured memory_bytes: 3580