#include <bits/stdc++.h>
#include <cmath>
#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;
using namespace std;
typedef long long ll;
//typedef unsigned long long ll;

#define rep(i, n) for (int i = 0; i < (n); ++i)
//#define rep(i, n) for (ll i = 0; i < (n); ++i)
//#define sz(x) ll(x.size())
//typedef pair<ll, int> P;
//typedef pair<ll, ll> P;
//const double INF = 1e10;
//const ll INF = LONG_LONG_MAX / 100;
//const ll INF = (1ll << 31) - 1;
//const ll INF = 1e15;
const ll MINF = LONG_LONG_MIN;
//const int INF = INT_MAX / 10;
#define cmin(x, y) x = min(x, y)
#define cmax(x, y) x = max(x, y)
//typedef pair<int, int> P;
//typedef pair<double, double> P;

//bool contain(set<P> &s, P a) { return s.find(a) != s.end(); }

//ifstream myfile("C:\\Users\\riku\\Downloads\\0_00.txt");
//ofstream outfile("log.txt");
//outfile << setw(6) << setfill('0') << prefecture << setw(6) << setfill('0') << rank << endl;
// std::cout << std::bitset<8>(9);
const int mod = 1000000007;
typedef priority_queue<long long, vector<long long>, greater<long long> > PQ_ASK;


void print_line(vector<ll> &line) {
    if (line.size() == 0ll) {
        cout << endl;
        return;
    }
    for (ll i = 0; i < line.size(); i++) {
        cout << line[i];
        if (i == line.size() - 1) cout << endl;
        else cout << ' ';
    }
}

template<typename type>
class Complex {
public :
    type real, imag;


    Complex(type re = 0, type im = 0): real(re), imag(im) {}
    Complex(const Complex &c) { real = c.real; imag = c.imag;};


    inline Complex operator + (const Complex& c) {
        return Complex(real + c.real, imag + c.imag);
    }

    inline Complex operator - (const Complex& c) {
        return Complex(real - c.real, imag - c.imag);
    }

    inline Complex operator * (const Complex& c) {
        return Complex(real * c.real - imag * c.imag, real * c.imag + imag * c.real);
    }

    inline Complex operator / (const Complex& c) {
        return Complex((real * c.real + imag * c.imag) / (c.real * c.real + c.imag * c.imag), (real * c.imag - imag * c.real)  / (c.real * c.real + c.imag * c.imag));
    }

    inline Complex & operator = (const Complex& c) {
        real = c.real; imag = c.imag;
        return *this;
    }

    inline type Real(){
        return real;
    }

    inline type Imag(){
        return imag;
    }
};


template<typename type>
class fast_Fourier_transform {
public:
    const long double pi = acos(-1);

    vector<type> discrete_Fourier_transform(vector<type> &f, int sign = 1){
        long long n = f.size();
        if(n == 1) return f;

        vector<type> f0(n>>1), f1(n>>1);
        type zeta, pow_zeta = {1,0};


        for(long long i = 0; i < f0.size(); i++){
            f0[i] = f[2 * i + 0];
        }

        for(long long i = 0; i < f1.size(); i++){
            f1[i] = f[2 * i + 1];
        }

        f0 = discrete_Fourier_transform(f0, sign);

        f1 = discrete_Fourier_transform(f1, sign);

        zeta = type(cos(2 * pi / n), sign * sin(2 * pi / n));

        for(long long i = 0; i < n; i++){
            f[i] = f0[i % (n>>1)] + pow_zeta * f1[i % (n>>1)];
            pow_zeta = pow_zeta * zeta;
        }

        return f;
    }

    vector<type> inverse_discrete_Fourier_transform(vector<type> &f){
        vector<type> ff = discrete_Fourier_transform(f, -1);

        for(int i = 0; i < f.size(); i++){
            ff[i] = (ff[i] + type(0.5, 0)) / type(f.size(), 0);
        }

        return ff;
    }

    vector<type> multiply(vector<type> &g, vector<type> &h){
        long long n = 1;
        vector<type> ff, gg, hh;

        while(n < g.size() + h.size() + 0){
            n <<= 1;
        }
        g.resize(n, {0,0});
        h.resize(n, {0,0});
        ff.resize(n);

        gg = discrete_Fourier_transform(g);
        hh = discrete_Fourier_transform(h);

        for(long long i = 0; i < n; i++){
            ff[i] = gg[i] * hh[i];
        }

        return inverse_discrete_Fourier_transform(ff);
    }

};

signed main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout<<fixed<<setprecision(10);

    int N, sign = 1;
    long double re, im;
    string a, b;
    int as, bs;
    vector<int> ans;
    vector<Complex<long double>> A, B, C;
    fast_Fourier_transform<Complex<long double>> fft;


    cin>>a>>b;

    as = a.size();
    bs = b.size();
    A.resize(a.size());
    B.resize(b.size());



    for(int i = 0, f = 0, p = a.size()-1, z = 0; i < a.size(); i++){
        if(a[i] == '-'){
            sign *= -1;
            A.resize(a.size()-1);
            as--;
        } else {
            A[z++].real = a[p--] - '0';
        }
    }

    for(int i = 0, f = 0, p = b.size()-1, z = 0; i < b.size(); i++){
        if(b[i] == '-'){
            sign *= -1;
            B.resize(b.size()-1);
            bs--;
        } else {
            B[z++].real = b[p--] - '0';
        }
    }

    C = fft.multiply(A, B);

    if(sign == -1 && a != "0" && b != "0"){
        cout<<"-";
    }
    int num = 0, lz = true;
    for(int i = 0; i < C.size(); i++){
        int temp = (int)(C[i].Real()+ 0.5) + num;
        num = temp/10;

        ans.push_back(temp%10);

    }
    while(num){
        ans.push_back(num%10);
        num /= 10;
    }

    for(int i = ans.size()-1, l = true; i >= 0; i--){
        if(l){
            if(ans[i]){
                cout<<ans[i];
                l = false;
            }
        } else {
            cout<<ans[i];
        }

        if(!i && l) cout<<0;
    }


    cout<<endl;


    return 0;
}


Measured memory_bytes: 122564