Problem p02625 (C++) — buggy submission, verdict: Time Limit Exceeded

#define NDEBUG
NDEBUG

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

template <class T> using vec = std::vector<T>;

// TC_REMOVE_BEGIN
/// caide keep
bool __hack = std::ios::sync_with_stdio(false);
/// caide keep
auto __hack1 = cin.tie(nullptr);
// TC_REMOVE_END

// Section with adoption of array and vector algorithms.

// #include <ext/pb_ds/tree_policy.hpp>
// #include <ext/pb_ds/assoc_container.hpp>
//
// template <class T> using StdTree = tree<T, null_type, less<T>,
// rb_tree_tag,tree_order_statistics_node_update>;

namespace template_util {

constexpr int bytecount(uint64_t x) { return x ? 1 + bytecount(x >> 8) : 0; }

template <int N> struct bytetype {};

/// caide keep
template <uint64_t N> struct minimal_uint : bytetype<bytecount(N)> {};
} // namespace template_util

template <class T> T next(istream &in) {
  T ret;
  in >> ret;
  return ret;
}

template <typename T> static constexpr T wrap_pos(T a, T m) {
  return a < 0 ? a + m : a;
}

// m must be positive
template <typename T> static constexpr T mod(T a, T m) {
  return wrap_pos(a % m, m);
}

template <typename T> static constexpr T inverse2(T a, T m) {
  return a <= 1 ? a : mod((1 - inverse2(m % a, a) * m) / a, m);
}

template <typename T> static constexpr T inverse(T a, T m) {
  return inverse2(mod(a, m), m);
}

template <typename T, typename C, T Modulus> class MR {
private:
  struct tag_plus {};  // indicates value is in range [0, 2 * Modulus)
  struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
  struct tag_good {};  // indicates value is in range

  //  T value;

  static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0,
                "compute type is too small");
  static_assert(Modulus < std::numeric_limits<T>::max() / 2,
                "storage type is too small");

  static constexpr T reduce(T value, tag_plus) {
    return value >= Modulus ? value - Modulus : value;
  }

  static constexpr T reduce(T value, tag_minus) {
    return value < 0 ? value + Modulus : value;
  }

  static constexpr T reduce(T value, tag_good) { return value; }

public:
  T value;

  constexpr MR() : value(0) {}
  constexpr MR(C value) : value(reduce(value % Modulus, tag_minus())) {}
  template <typename tag_t>
  constexpr MR(T value, tag_t tag) : value(reduce(value, tag)) {}

  MR &operator=(C value) {
    this->value = reduce(value % Modulus, tag_minus());
    return *this;
  }

  constexpr MR operator+(MR b) const { return MR(value + b.value, tag_plus()); }
  constexpr MR operator-(MR b) const {
    return MR(value - b.value, tag_minus());
  }
  constexpr MR operator*(MR b) const {
    return MR(C(value) * C(b.value) % Modulus, tag_good());
  }

  constexpr T get() const { return value; }

  // These are only valid if the dividend is relatively prime to the modulus
  constexpr MR inverse() const {
    return MR(::inverse(C(value), C(Modulus)), tag_good());
  }
  constexpr MR operator/(MR b) const { return *this * b.inverse(); }
};

template <typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr) {
  return o << mr.get();
}

// template <class T>
// T gcd(T a, T b) {
//     return b == 0 ? a : gcd(b, a % b);
// }

// TODO extended gcd

// MD implementation of factorials and binomial

template <class T> vector<T> getFactorials(int n) {
  vector<T> res(n);
  res[0] = T(1);
  for (int i = 1; i < n; ++i) {
    res[i] = res[i - 1] * i;
  }
  return res;
}

// TODO(alf): Tests

//
// int64_t lcm(const vector<int64_t>& a) {
//    int64_t res = a[0];
//    for (int i = 1; i < (int)a.size(); ++i) {
//        int64_t g = gcd(res, a[i]);
//        res *= a[i];
//        res /= g;
//    }
//    return res;
//}
//
// int64_t lcm(int64_t a, int64_t b) {
//    return (a * b / gcd(a, b));
//}

// TODO: test on timus problem
// vector<double> polynomeEquationSolve() {}

// Algorithms

typedef MR<int, int64_t, 1000000007> md;

vec<md> fs;
vec<md> fs2;
vec<md> rfs;

md C(int n, int k) { return fs[n] * rfs[k] * rfs[n - k]; }

md getAll(int n, int m) {
  auto c1 = C(m, n);
  return c1 * c1 * fs2[n];
}

void solve(istream &in, ostream &out) {
  auto n = next<int>(in);
  auto m = next<int>(in);
  fs = getFactorials<md>(m + 1);
  rfs = vec<md>(m + 1);
  fs2 = vec<md>(m + 1);
  rfs[0] = rfs[1] = 1;
  fs2[0] = fs2[1] = 1;
  for (int i = 2; i < m + 1; ++i) {
    fs2[i] = fs[i] * fs[i];
    rfs[i] = md(1) / fs[i];
  }
  md res = getAll(n, m);
  for (int common = 1; common <= n; ++common) {
    md selectCommon = C(m, common);
    md selectPositions = C(n, common);
    md rest = getAll(n - common, m - common);
    md count = selectCommon * selectPositions * fs[common] * rest;
    if (common % 2 == 1) {
      res = res - count;
    } else {
      res = res + count;
    }
  }

  out << res << "\\n";
}

// #include <fstream>

int main() {
  //  ifstream fin("bridges.in");
  //  ofstream fout("bridges.out");
  solve(cin, cout);
  //  solve(fin, fout);
  return 0;
}


Error: TLE

Fixed submission:

#define NDEBUG
NDEBUG

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

template <class T> using vec = std::vector<T>;

// TC_REMOVE_BEGIN
/// caide keep
bool __hack = std::ios::sync_with_stdio(false);
/// caide keep
auto __hack1 = cin.tie(nullptr);
// TC_REMOVE_END

// Section with adoption of array and vector algorithms.

// #include <ext/pb_ds/tree_policy.hpp>
// #include <ext/pb_ds/assoc_container.hpp>
//
// template <class T> using StdTree = tree<T, null_type, less<T>,
// rb_tree_tag,tree_order_statistics_node_update>;

namespace template_util {

constexpr int bytecount(uint64_t x) { return x ? 1 + bytecount(x >> 8) : 0; }

template <int N> struct bytetype {};

/// caide keep
template <uint64_t N> struct minimal_uint : bytetype<bytecount(N)> {};
} // namespace template_util

template <class T> T next(istream &in) {
  T ret;
  in >> ret;
  return ret;
}

template <typename T> static constexpr T wrap_pos(T a, T m) {
  return a < 0 ? a + m : a;
}

// m must be positive
template <typename T> static constexpr T mod(T a, T m) {
  return wrap_pos(a % m, m);
}

template <typename T> static constexpr T inverse2(T a, T m) {
  return a <= 1 ? a : mod((1 - inverse2(m % a, a) * m) / a, m);
}

template <typename T> static constexpr T inverse(T a, T m) {
  return inverse2(mod(a, m), m);
}

template <typename T, typename C, T Modulus> class MR {
private:
  struct tag_plus {};  // indicates value is in range [0, 2 * Modulus)
  struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
  struct tag_good {};  // indicates value is in range

  //  T value;

  static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0,
                "compute type is too small");
  static_assert(Modulus < std::numeric_limits<T>::max() / 2,
                "storage type is too small");

  static constexpr T reduce(T value, tag_plus) {
    return value >= Modulus ? value - Modulus : value;
  }

  static constexpr T reduce(T value, tag_minus) {
    return value < 0 ? value + Modulus : value;
  }

  static constexpr T reduce(T value, tag_good) { return value; }

public:
  T value;

  constexpr MR() : value(0) {}
  constexpr MR(C value) : value(reduce(value % Modulus, tag_minus())) {}
  template <typename tag_t>
  constexpr MR(T value, tag_t tag) : value(reduce(value, tag)) {}

  constexpr MR operator+(MR b) const { return MR(value + b.value, tag_plus()); }
  constexpr MR operator-(MR b) const {
    return MR(value - b.value, tag_minus());
  }
  constexpr MR operator*(MR b) const {
    return MR(C(value) * C(b.value) % Modulus, tag_good());
  }

  constexpr T get() const { return value; }

  // These are only valid if the dividend is relatively prime to the modulus
  constexpr MR inverse() const {
    return MR(::inverse(C(value), C(Modulus)), tag_good());
  }
  constexpr MR operator/(MR b) const { return *this * b.inverse(); }
};

template <typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr) {
  return o << mr.get();
}

// template <class T>
// T gcd(T a, T b) {
//     return b == 0 ? a : gcd(b, a % b);
// }

// TODO extended gcd

// MD implementation of factorials and binomial

template <class T> vector<T> getFactorials(int n) {
  vector<T> res(n);
  res[0] = T(1);
  for (int i = 1; i < n; ++i) {
    res[i] = res[i - 1] * i;
  }
  return res;
}

// TODO(alf): Tests

//
// int64_t lcm(const vector<int64_t>& a) {
//    int64_t res = a[0];
//    for (int i = 1; i < (int)a.size(); ++i) {
//        int64_t g = gcd(res, a[i]);
//        res *= a[i];
//        res /= g;
//    }
//    return res;
//}
//
// int64_t lcm(int64_t a, int64_t b) {
//    return (a * b / gcd(a, b));
//}

// TODO: test on timus problem
// vector<double> polynomeEquationSolve() {}

// Algorithms

typedef MR<int, int64_t, 1000000007> md;

vec<md> fs;

md C(int n, int k) { return fs[n] / fs[k] / fs[n - k]; }

md getAll(int n, int m) { return C(m, n) * C(m, n) * fs[n] * fs[n]; }

void solve(istream &in, ostream &out) {
  auto n = next<int>(in);
  auto m = next<int>(in);
  fs = getFactorials<md>(m + 1);

  md res = getAll(n, m);
  //  dbg("total", res);
  for (int common = 1; common <= n; ++common) {

    md selectCommon = C(m, common);
    md selectPositions = C(n, common);
    md rest = getAll(n - common, m - common);

    md count = selectCommon * selectPositions * fs[common] * rest;

    //    dbg("common", common, selectCommon, selectPositions, rest, count);
    if (common % 2 == 1) {
      res = res - count;
    } else {
      res = res + count;
    }
    //    dbg(res);
  }

  out << res << "\\n";
}

// #include <fstream>

int main() {
  //  ifstream fin("bridges.in");
  //  ofstream fout("bridges.out");
  solve(cin, cout);
  //  solve(fin, fout);
  return 0;
}