結果
| 問題 |
No.1001 注文の多い順列
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-02-28 22:17:47 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 126 ms / 2,000 ms |
| コード長 | 3,720 bytes |
| コンパイル時間 | 1,859 ms |
| コンパイル使用メモリ | 174,044 KB |
| 実行使用メモリ | 51,840 KB |
| 最終ジャッジ日時 | 2024-10-13 17:52:15 |
| 合計ジャッジ時間 | 4,203 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 31 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()
template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) noexcept {
return std::vector<T>(n, std::forward<T>(val));
}
template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) noexcept {
return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
template<i64 M>
constexpr i64 euinv(i64 val) {
i64 a = M, b = val;
i64 x = 0, u = 1;
while (b) {
i64 t = a / b;
swap(a -= t * b, b);
swap(x -= t * u, u);
}
return x < 0 ? x + M : x;
}
template<i64 M>
struct modint {
i64 a;
constexpr modint(const i64 x = 0) noexcept: a((x % M + M) % M) {}
constexpr i64 value() const noexcept { return a; }
constexpr modint inv() const noexcept { return modint(euinv<M>(a)); }
constexpr modint pow(i64 r) const noexcept {
modint ans(1);
modint aa = *this;
while(r) {
if(r & 1) {
ans *= aa;
}
aa *= aa;
r >>= 1;
}
return ans;
}
constexpr modint& operator+=(const modint r) noexcept {
a += r.a;
if(a >= M) a -= M;
return *this;
}
constexpr modint& operator=(const i64 r) {
a = (r % M + M) % M;
return *this;
}
constexpr modint& operator-=(const modint r) noexcept {
a -= r.a;
if(a < 0) a += M;
return *this;
}
constexpr modint& operator*=(const modint r) noexcept {
a = a * r.a % M;
return *this;
}
constexpr modint& operator/=(modint r) noexcept {
i64 ex = M - 2;
while(ex) {
if(ex & 1) {
*this *= r;
}
r *= r;
ex >>= 1;
}
return *this;
}
constexpr modint operator+(const modint r) const {
return modint(*this) += r;
}
constexpr modint operator-(const modint r) const {
return modint(*this) -= r;
}
constexpr modint operator*(const modint r) const {
return modint(*this) *= r;
}
constexpr modint operator/(const modint r) const {
return modint(*this) /= r;
}
constexpr bool operator!=(const modint r) const {
return this->value() != r.value();
}
};
template<const i64 M>
std::ostream& operator<<(std::ostream& os, const modint<M>& m) {
os << m.value();
return os;
}
using fp = modint<(i64)(1e9 + 7)>;
fp dp[3010][6020];
int main() {
i64 N;
cin >> N;
vector<i64> T(N), X(N);
rep(i,0,N) {
cin >> T[i] >> X[i];
}
vector<i64> en(N + 1);
vector<i64> st(N + 1);
rep(i,0,N) {
if(T[i] == 1) st[X[i]]++;
else en[X[i]]++;
}
rep(i,0,N) {
st[i + 1] += st[i];
en[i + 1] += en[i];
}
vector<fp> fact(100000);
vector<fp> invf(100000);
fact[0] = fp(1);
rep(i,1,fact.size()) {
fact[i] = fact[i - 1] * fp(i);
}
invf.back() = fp(1) / fact.back();
for(i64 i = invf.size() - 1; i --> 0;) {
invf[i] = invf[i + 1] * fp(i + 1);
}
dp[0][0] = fp(1);
rep(i,0,N) {
rep(j,0,N + 1) {
if(j > st[i + 1]) continue;
// j <= en[i + 1]
if(st[i + 1] - j >= 1) {
// use (i + 1)
i64 remain = i - j - en[i];
if(remain >= en[i + 1] - en[i]) {
i64 r = en[i + 1] - en[i];
dp[i + 1][j + 1] += dp[i][j] * (st[i + 1] - j) * fact[remain] * invf[remain - r];
}
}
{
// dont use (i + 1)
i64 remain = i + 1 - j - en[i];
if(remain >= en[i + 1] - en[i]) {
i64 r = en[i + 1] - en[i];
dp[i + 1][j] += dp[i][j] * fact[remain] * invf[remain - r];
}
}
}
}
cout << dp[N][st.back()] << endl;
}