QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#145312 | #6410. Classical DP Problem | nhuang685 | WA | 2ms | 3652kb | C++20 | 5.2kb | 2023-08-22 05:28:28 | 2023-08-22 05:28:30 |
Judging History
answer
/**
* @file qoj6410-1.cpp
* @author n685
* @brief
* @date 2023-08-21
*
*
*/
#include <bits/stdc++.h>
#ifdef LOCAL
std::ifstream cin;
std::ofstream cout;
using std::cerr;
#else
using std::cin;
using std::cout;
#define cerr \
if (false) \
std::cerr
#endif
#ifdef LOCAL
#include "dd/debug.h"
#define dbg(...) lineInfo(__LINE__, #__VA_ARGS__), dbg1(__VA_ARGS__)
#define dbgR(...) lineInfo(__LINE__, #__VA_ARGS__), dbg2(__VA_ARGS__)
void nline() { cerr << '\n'; }
#else
#define dbg(...) 42
#define dbgR(...) 420
void nline() {}
#endif
template <class T> constexpr std::pair<T, T> exEucl(T a, T b) {
if (a < b) {
// auto [x, y] = exEucl(b, a);
T x, y;
std::tie(x, y) = exEucl(b, a);
return {y, x};
}
if (b == 0) {
assert(a == 1);
return {1, 0};
}
// auto [x, y] = exEucl(b, a % b);
T x, y;
std::tie(x, y) = exEucl(b, a % b);
return {y, x - (a / b) * y};
}
template <
class T, class U,
typename std::enable_if<std::is_integral<U>::value, bool>::type = true>
constexpr T binpow(const T &val, U b) {
// 0^0 = 1
T res = 1, a = val;
while (b > 0) {
if (b % 2 == 1)
res *= a;
a *= a;
b /= 2;
}
return res;
}
template <class Md, class V = int64_t> struct Mod {
using T = typename std::decay<decltype(Md::value)>::type;
T val = 0;
template <class U> static constexpr T normalize(U val) {
if (val <= -Md::value || Md::value <= val)
val %= Md::value;
if (val < 0)
val += Md::value;
return static_cast<T>(val);
}
constexpr Mod() : val(0) {}
template <class U, typename std::enable_if<std::is_integral<U>::value,
bool>::type = true>
constexpr Mod(U _val) {
val = normalize(_val);
}
// addition
constexpr Mod &operator+=(Mod b) {
val += b.val;
if (val >= Md::value)
val -= Md::value;
return *this;
}
friend constexpr Mod operator+(Mod a, Mod b) { return (a += b); }
constexpr Mod &operator++() { return (*this += 1); }
constexpr Mod operator++(int) {
Mod res = *this;
++(*this);
return res;
}
// subtraction
constexpr Mod &operator-=(Mod b) {
val -= b.val;
if (val < 0)
val += Md::value;
return *this;
}
friend constexpr Mod operator-(Mod a, Mod b) { return (a -= b); }
constexpr Mod &operator--() { return (*this -= 1); }
constexpr Mod operator--(int) {
Mod res = *this;
--(*this);
return res;
}
// multiplication
constexpr Mod &operator*=(Mod b) {
val = static_cast<T>(static_cast<V>(val) * b.val % Md::value);
return *this;
}
friend constexpr Mod operator*(Mod a, Mod b) { return (a *= b); }
template <class U> constexpr Mod binpow(U b) const {
return ::binpow(*this, b);
}
constexpr Mod inv() const {
return Mod(exEucl(static_cast<V>(val), static_cast<V>(Md::value)).first);
// return binpow(Md::value - 2);
}
// comparison
constexpr bool operator==(Mod b) const { return (val == b.val); }
// constexpr auto operator<=>(const Mod &b) const = default;
constexpr bool operator!=(Mod b) const { return (val != b.val); }
constexpr bool operator<(Mod b) const { return (val < b.val); }
constexpr bool operator>(Mod b) const { return (val > b.val); }
constexpr bool operator<=(Mod b) const { return (val <= b.val); }
constexpr bool operator>=(Mod b) const { return (val >= b.val); }
// io
friend std::istream &operator>>(std::istream &in, Mod &a) {
V v;
in >> v;
a = Mod(v);
return in;
}
friend std::ostream &operator<<(std::ostream &out, const Mod &a) {
out << a.val;
return out;
}
// conversion
explicit constexpr operator T() const { return val; }
constexpr const T &operator()() const { return val; }
constexpr Mod operator-() const { return Mod(-val); }
};
constexpr int MOD = 998244353;
using Mint = Mod<std::integral_constant<std::decay<decltype(MOD)>::type, MOD>>;
int main() {
#ifdef LOCAL
cin.open("input.txt");
cout.rdbuf()->pubsetbuf(0, 0);
cout.open("output.txt");
#else
cin.tie(nullptr)->sync_with_stdio(false);
#endif
int n;
cin >> n;
std::vector<int> a(n + 1);
for (int i = 1; i <= n; ++i)
cin >> a[i];
std::reverse(a.begin() + 1, a.end());
int k = n;
for (int i = 1; i <= n - 1; ++i)
if (a[i] >= i && a[i + 1] < i + 1) {
k = i;
break;
}
Mint ans = 0;
auto solve = [&]() {
int t = a[k + 1];
std::vector<std::vector<Mint>> dp(k + 1, std::vector<Mint>(t + 1));
dp[0][0] = 1;
for (int i = 1; i <= k; ++i) {
for (int j = 0; j <= t; ++j) {
dp[i][j] += dp[i - 1][j] * (a[i] - (t - j));
if (j > 0)
dp[i][j] += dp[i - 1][j - 1] * (t - (j - 1));
}
}
ans += dp[k][t];
};
solve();
std::vector<int> na(n + 1, n);
for (int i = 1; i <= n - 1; ++i) {
for (int j = a[i]; j > a[i + 1]; --j)
na[j] = i;
}
a.swap(na);
solve();
Mint f = 1;
for (int i = 2; i <= k; ++i)
f *= i;
cout << k << ' ' << ans - f << '\n';
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 2ms
memory: 3652kb
input:
3 1 2 3
output:
2 6
result:
ok 2 number(s): "2 6"
Test #2:
score: 0
Accepted
time: 2ms
memory: 3500kb
input:
1 1
output:
1 1
result:
ok 2 number(s): "1 1"
Test #3:
score: -100
Wrong Answer
time: 2ms
memory: 3620kb
input:
2 1 1
output:
1 0
result:
wrong answer 2nd numbers differ - expected: '2', found: '0'