Little Petya loves training spiders. Petya has a board n × m in size. Each cell of the board initially has a spider sitting on it. After one second Petya chooses a certain action for each spider, and all of them humbly perform its commands. There are 5 possible commands: to stay idle or to move from current cell to some of the four side-neighboring cells (that is, one command for each of the four possible directions). Petya gives the commands so that no spider leaves the field. It is allowed for spiders to pass through each other when they crawl towards each other in opposite directions. All spiders crawl simultaneously and several spiders may end up in one cell. Petya wants to know the maximum possible number of spider-free cells after one second.

Input

The first line contains two space-separated integers n and m (1 ≤ n, m ≤ 40, n·m ≤ 40) — the board sizes.

Output

In the first line print the maximum number of cells without spiders.

Examples

Input

1 1


Output

0


Input

2 3


Output

4

Note

In the first sample the only possible answer is:

s

In the second sample one of the possible solutions is: 
    
    
      
    rdl  
    rul  
    

s denotes command "stay idle", l, r, d, u denote commands "crawl left", "crawl right", "crawl down", "crawl up", correspondingly.
#include <bits/stdc++.h>
using namespace std;
inline int in() {
  int32_t x;
  scanf("%d", &x);
  return x;
}
inline long long lin() {
  long long x;
  scanf("%lld", &x);
  return x;
}
inline string get() {
  char ch[2000010];
  scanf("%s", ch);
  return ch;
}
const int MAX_LG = 21;
const long long maxn = 1e5 + 10;
const long long maxm = 1e6 + 10;
const long long base = 29;
const long long mod = 1e9 + 7;
const long long INF = 1e8 + 10;
const long long MASK = (1 << 7);
long long dp[41][MASK][MASK], n, m, res;
bool mark[50], mark2[50];
int32_t main() {
  n = in(), m = in();
  if (n > m) swap(n, m);
  memset(dp, -63, sizeof dp);
  dp[0][0][0] = n;
  for (long long column = 1; column <= m; column++) {
    for (long long premask = 0; premask < (1 << n); premask++) {
      for (long long curmask = 0; curmask < (1 << n); curmask++) {
        long long preVal = dp[column - 1][premask][curmask];
        if (preVal <= -INF) continue;
        for (long long curmask2 = 0; curmask2 < (1 << n); curmask2++) {
          if ((curmask2 & curmask) != curmask) continue;
          for (long long nextmask = 0; nextmask < (1 << n); nextmask++) {
            if (nextmask && column == m) continue;
            bool fl = true;
            long long premask2 = premask;
            for (long long pt = 0; pt <= n; pt++) mark[pt] = mark2[pt] = false;
            for (long long pt = 0; pt < n; pt++) {
              if (nextmask & (1 << pt)) mark[pt] = true;
              if ((curmask2 ^ curmask) & (1 << pt)) mark2[pt] = true;
            }
            for (long long pt = 0; pt < n; pt++) {
              if (mark2[pt]) {
                bool ok = false;
                for (long long j = max(0ll, pt - 1); j <= min(pt, n - 1); j++) {
                  if (!mark[j]) {
                    mark[j] = true;
                    ok = true;
                    break;
                  }
                }
                if (!ok) fl = false;
              }
            }
            for (long long pt = 0; pt < n; pt++) {
              if (!mark[pt]) {
                bool ok = false;
                for (long long dx = -1; dx <= 1; dx++) {
                  if (pt + dx >= 0 && pt + dx < n &&
                      (curmask2 & (1 << (pt + dx)))) {
                    ok = true;
                  }
                }
                if (!ok) {
                  if (column == 1) {
                    fl = false;
                  } else {
                    premask2 |= (1 << pt);
                  }
                }
              }
            }
            if (!fl) continue;
            long long del =
                __builtin_popcountll(premask2 ^ premask) +
                __builtin_popcountll(curmask2 ^ curmask) -
                (column == m ? 0 : n - __builtin_popcountll(nextmask));
            dp[column][curmask2][nextmask] =
                max(dp[column][curmask2][nextmask], preVal - del);
          }
        }
      }
    }
    if (column == m) {
      for (long long mask = 0; mask < MASK; mask++)
        res = max(res, dp[column][mask][0]);
    }
  }
  cout << res << "\n";
}
