Problem p03406 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int MOD = 1e9 + 7;

ll modinv(ll a, ll m = MOD) {
  assert(1 <= a);
  assert(a < m);
  return a == 1 ? 1 : m - modinv(m % a, a) * m / a;
}

const int MAXN = 16;
const int MAXM = 16;
int N, M;
int A[MAXM];

int dp[MAXM + 1][1 << MAXN];

const int MAXV = (1 << 16) + 10;
int fact[MAXV];
int ifact[MAXV];

int choose(int a, int b) {
  if (a >= b && b >= 0) {
    return fact[a] * ll(ifact[a - b]) % MOD * ifact[b] % MOD;
  } else {
    return 0;
  }
}

int main() {
  freopen("shiratsuyu.in", "r", stdin), freopen("shiratsuyu.out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  fact[0] = 1;
  for (int i = 1; i < MAXV; i++) {
    fact[i] = ll(i) * fact[i - 1] % MOD;
  }
  ifact[MAXV - 1] = modinv(fact[MAXV - 1]);
  for (int i = MAXV - 1; i >= 1; i--) {
    ifact[i - 1] = ll(i) * ifact[i] % MOD;
  }

  cin >> N >> M;
  for (int i = 0; i < M; i++) {
    cin >> A[i];
    A[i]--;
  }
  sort(A, A + M, greater<int>());

  dp[0][0] = 1;
  for (int k = 0; k < M; k++) {
    for (int m = 0; m < (1 << N); m++) {
      dp[k + 1][m] += dp[k][m];
      dp[k + 1][m] %= MOD;
      int bigger = (1 << N) - 1 - A[k] - m;
      for (int i = 0; i < N; i++) {
        if (m & (1 << i))
          continue;
        dp[k + 1][m | (1 << i)] += MOD - choose(bigger, (1 << i) - 1) *
                                             ll(dp[k][m]) % MOD * fact[1 << i] %
                                             MOD;
        dp[k + 1][m | (1 << i)] %= MOD;
      }
    }
  }

  ll ans = 0;
  for (int m = 0; m < (1 << N); m++) {
    int v = ll(dp[M][m]) * fact[(1 << N) - m - 1] % MOD;
    ans += v;
    ans %= MOD;
  }
  ans *= 1 << N;
  ans %= MOD;
  cout << ans << '\n';

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int MOD = 1e9 + 7;

ll modinv(ll a, ll m = MOD) {
  assert(1 <= a);
  assert(a < m);
  return a == 1 ? 1 : m - modinv(m % a, a) * m / a;
}

const int MAXN = 16;
const int MAXM = 16;
int N, M;
int A[MAXM];

int dp[MAXM + 1][1 << MAXN];

const int MAXV = (1 << 16) + 10;
int fact[MAXV];
int ifact[MAXV];

int choose(int a, int b) {
  if (a >= b && b >= 0) {
    return fact[a] * ll(ifact[a - b]) % MOD * ifact[b] % MOD;
  } else {
    return 0;
  }
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  fact[0] = 1;
  for (int i = 1; i < MAXV; i++) {
    fact[i] = ll(i) * fact[i - 1] % MOD;
  }
  ifact[MAXV - 1] = modinv(fact[MAXV - 1]);
  for (int i = MAXV - 1; i >= 1; i--) {
    ifact[i - 1] = ll(i) * ifact[i] % MOD;
  }

  cin >> N >> M;
  for (int i = 0; i < M; i++) {
    cin >> A[i];
    A[i]--;
  }
  sort(A, A + M, greater<int>());

  dp[0][0] = 1;
  for (int k = 0; k < M; k++) {
    for (int m = 0; m < (1 << N); m++) {
      dp[k + 1][m] += dp[k][m];
      dp[k + 1][m] %= MOD;
      int bigger = (1 << N) - 1 - A[k] - m;
      for (int i = 0; i < N; i++) {
        if (m & (1 << i))
          continue;
        dp[k + 1][m | (1 << i)] += MOD - choose(bigger, (1 << i) - 1) *
                                             ll(dp[k][m]) % MOD * fact[1 << i] %
                                             MOD;
        dp[k + 1][m | (1 << i)] %= MOD;
      }
    }
  }

  ll ans = 0;
  for (int m = 0; m < (1 << N); m++) {
    int v = ll(dp[M][m]) * fact[(1 << N) - m - 1] % MOD;
    ans += v;
    ans %= MOD;
  }
  ans *= 1 << N;
  ans %= MOD;
  cout << ans << '\n';

  return 0;
}