public BigDecimal runMonty(int[] a) {
    String serial = serialize(a);
    if (montydp.containsKey(serial)) {
      return montydp.get(serial);
    }

    List<Swap> swaps = new ArrayList<Swap>();
    for (int x = 0; x < a.length; x++) {
      for (int y = x + 1; y < a.length; y++) {
        if (a[x] > a[y]) {
          swaps.add(new Swap(x, y));
        }
      }
    }
    //System.out.println(swaps.size());
    if (swaps.size() == 0) {
      BigDecimal zero = new BigDecimal(0);
      montydp.put(serial, zero);
      return zero;
    } else {
      BigDecimal expected = new BigDecimal(Math.pow(a.length, 2));
      expected.setScale(100);
      expected = expected.divide(new BigDecimal(2 * swaps.size()), 100, BigDecimal.ROUND_HALF_UP);
      
      for (int x = 0; x < swaps.size(); x++) {
        int[] newa = a.clone();
        swap(newa, swaps.get(x).start, swaps.get(x).end);
        expected = expected.add(runMonty(newa).divide(
            new BigDecimal(swaps.size()), 100, BigDecimal.ROUND_HALF_UP));
      }
      montydp.put(serial, expected);
      return expected;
    }
  }