#include <bits/stdc++.h>
using namespace std;
struct MaximumFlow {
  struct Edge {
    int from, to, cap, rev;
    Edge(int from, int to, int cap) : from(from), to(to), cap(cap){};
  };
  vector<vector<Edge>> G;
  vector<int> work, level;
  int N, src, sink;
  MaximumFlow(int N, int src, int sink) : N(N), src(src), sink(sink) {
    G.resize(N);
    work.resize(N);
    level.resize(N);
  }
  void add_edge(int f, int t, int cap) {
    G[f].emplace_back(f, t, cap);
    G[t].emplace_back(t, f, 0);
    G[f].back().rev = G[t].size() - 1;
    G[t].back().rev = G[f].size() - 1;
  }
  void add_edge_from_source(int t, int cap) { add_edge(src, t, cap); }
  void add_edge_to_sink(int f, int cap) { add_edge(f, sink, cap); }
  int dfs(int c, int MF = 0x7fffffff) {
    if (c == sink) {
      return MF;
    }
    int flow;
    for (int &i = work[c]; i < G[c].size(); i++) {
      auto &e = G[c][i];
      if (e.cap > 0 && level[e.to] == level[e.from] + 1 &&
          (flow = dfs(e.to, min(e.cap, MF)))) {
        e.cap -= flow;
        G[e.to][e.rev].cap += flow;
        return flow;
      }
    }
    return 0;
  }
  int flow() {
    int ret = 0;
    queue<int> Q;
    for (;;) {
      int flow = 0;
      fill(level.begin(), level.end(), -1);
      Q.push(src);
      level[src] = 0;
      while (!Q.empty()) {
        int c = Q.front();
        Q.pop();
        for (auto &e : G[c]) {
          if (e.cap > 0 && level[e.to] == -1) {
            level[e.to] = level[e.from] + 1;
            Q.push(e.to);
          }
        }
      }
      fill(work.begin(), work.end(), 0);
      while (int temp = dfs(src)) {
        flow += temp;
      }
      if (flow == 0) {
        break;
      }
      ret += flow;
    }
    return ret;
  }
};
int nN, nM;
const int dx[] = {-3, -2, -2, -1, 1, 0}, dy[] = {0, -1, 1, -2, -2, -3};
int convert(int x, int y) { return x * nM + y; }
bool valid_coord(int x, int y) { return 0 <= x && x < nN && 0 <= y && y < nM; }
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  ((void)0);
  ((void)0);
  int N, M;
  cin >> N >> M;
  if (N > 12) {
    nN = N % 12 + 12;
  } else {
    nN = N;
  }
  if (M > 12) {
    nM = M % 12 + 12;
  } else {
    nM = M;
  }
  MaximumFlow mf(nN * nM + 2, nN * nM, nN * nM + 1);
  for (int i = 0; i < nN; i++) {
    for (int j = 0; j < nM; j++) {
      if ((i + j) & 1) {
        mf.add_edge_from_source(convert(i, j), 2);
        for (int k = 0; k < 6; k++) {
          if (valid_coord(i + dx[k], j + dy[k])) {
            mf.add_edge(convert(i, j), convert(i + dx[k], j + dy[k]), 2);
          }
        }
      } else {
        mf.add_edge_to_sink(convert(i, j), 2);
        for (int k = 0; k < 6; k++) {
          if (valid_coord(i + dx[k], j + dy[k])) {
            mf.add_edge(convert(i + dx[k], j + dy[k]), convert(i, j), 2);
          }
        }
      }
    }
  }
  cout << 1LL * N * M - (nN * nM - mf.flow()) << '\n';
  return 0;
}
