Problem p03253 (C++)

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

typedef long long ll;

template <typename T> void out(T x) {
  cout << x << endl;
  exit(0);
}
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;
const ll mod = 1e9 + 7;

ll fac[maxn], ifac[maxn];

ll modpow(ll, ll);
ll inv(ll);
ll nck(ll, ll);
void build();
void testlib();

ll n, m;
ll dp[50][50]; // # way to choose i factors to make v[j]
bool used[50][maxn];

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  build();
  cin >> n >> m;

  vector<ll> v;
  for (ll i = 1; i * i <= m; i++) {
    if (m % i)
      continue;
    v.push_back(i);
    v.push_back(m / i);
  }
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()), v.end());

  for (int i = 0; i < int(v.size()); i++) {
    for (int j = 0; j < int(v.size()); j++) {
      if (j > i && v[j] % v[i] == 0) {
        used[i][j] = true;
      }
    }
  }

  dp[0][0] = 1;

  for (int i = 0; i < 33; i++) {
    for (int j = 0; j < int(v.size()); j++) {
      for (int k = 0; k < int(v.size()); k++) {
        if (used[j][k]) {
          dp[i + 1][k] += dp[i][j];
          dp[i + 1][k] %= mod;
        }
      }
    }
  }

  // for (int i=0; i<5; i++) {
  //   for (int j=0; j<int(v.size()); j++) {
  //     cout<<dp[i][j]<<" ";
  //   }
  //   cout<<endl;
  // }

  ll ans = 0;
  for (int i = 0; i < 33; i++) {
    ll cur = nck(n, i) * dp[i][int(v.size()) - 1];
    cur %= mod;
    ans += cur;
    ans %= mod;
  }

  cout << ans << endl;

  return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

ll modpow(ll x, ll y) {
  x %= mod;
  ll res = 1;
  while (y > 0) {
    if (y % 2 == 1) {
      res *= x;
      res %= mod;
    }
    x = x * x;
    x %= mod;
    y = y / 2;
  }
  return res;
}

ll inv(ll x) {
  assert(x != 0);
  return modpow(x, mod - 2);
}

void build() {
  fac[0] = ifac[0] = 1;
  for (int i = 1; i < maxn; i++) {
    fac[i] = fac[i - 1] * i;
    fac[i] %= mod;
    ifac[i] = inv(fac[i]);
    ifac[i] %= mod;
  }
}

ll nck(ll n, ll k) {
  assert(n >= 0 && k >= 0);
  if (k > n)
    return 0;
  return (((fac[n] * ifac[k]) % mod) * ifac[n - k]) % mod;
}

void testlib() {
  assert(modpow(1, 1) == 1);
  assert(modpow(4, 2) == 16);
  assert(modpow(2, 5) == 32);
  assert(fac[3] == 6);
  assert(nck(4, 2) == 6);
  assert(nck(10, 2) == 45);
}


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

typedef long long ll;

template <typename T> void out(T x) {
  cout << x << endl;
  exit(0);
}
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;
const ll mod = 1e9 + 7;

ll fac[maxn], ifac[maxn];

ll modpow(ll, ll);
ll inv(ll);
ll nck(ll, ll);
void build();
void testlib();

ll n, m;
ll dp[50][maxn]; // # way to choose i factors to make v[j]
bool used[3009][3009];

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  build();
  cin >> n >> m;

  vector<ll> v;
  for (ll i = 1; i * i <= m; i++) {
    if (m % i)
      continue;
    v.push_back(i);
    v.push_back(m / i);
  }
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()), v.end());

  for (int i = 0; i < int(v.size()); i++) {
    for (int j = 0; j < int(v.size()); j++) {
      if (j > i && v[j] % v[i] == 0) {
        used[i][j] = true;
      }
    }
  }

  dp[0][0] = 1;

  for (int i = 0; i < 33; i++) {
    for (int j = 0; j < int(v.size()); j++) {
      for (int k = 0; k < int(v.size()); k++) {
        if (used[j][k]) {
          dp[i + 1][k] += dp[i][j];
          dp[i + 1][k] %= mod;
        }
      }
    }
  }

  // for (int i=0; i<5; i++) {
  //   for (int j=0; j<int(v.size()); j++) {
  //     cout<<dp[i][j]<<" ";
  //   }
  //   cout<<endl;
  // }

  ll ans = 0;
  for (int i = 0; i < 33; i++) {
    ll cur = nck(n, i) * dp[i][int(v.size()) - 1];
    cur %= mod;
    ans += cur;
    ans %= mod;
  }

  cout << ans << endl;

  return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

ll modpow(ll x, ll y) {
  x %= mod;
  ll res = 1;
  while (y > 0) {
    if (y % 2 == 1) {
      res *= x;
      res %= mod;
    }
    x = x * x;
    x %= mod;
    y = y / 2;
  }
  return res;
}

ll inv(ll x) {
  assert(x != 0);
  return modpow(x, mod - 2);
}

void build() {
  fac[0] = ifac[0] = 1;
  for (int i = 1; i < maxn; i++) {
    fac[i] = fac[i - 1] * i;
    fac[i] %= mod;
    ifac[i] = inv(fac[i]);
    ifac[i] %= mod;
  }
}

ll nck(ll n, ll k) {
  assert(n >= 0 && k >= 0);
  if (k > n)
    return 0;
  return (((fac[n] * ifac[k]) % mod) * ifac[n - k]) % mod;
}

void testlib() {
  assert(modpow(1, 1) == 1);
  assert(modpow(4, 2) == 16);
  assert(modpow(2, 5) == 32);
  assert(fac[3] == 6);
  assert(nck(4, 2) == 6);
  assert(nck(10, 2) == 45);
}