This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include<bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < ll(n); ++i)
#define rep2(i, s, n) for (ll i = ll(s); i < ll(n); ++i)
#define rrep(i, n) for (ll i = ll(n) - 1; i >= 0; i--)
#define SZ(a) int(a.size())
using namespace std;
using ll = long long;
class mint {
ll x;
static int mod;
public:
static void set_mod(int _mod) { mod = _mod; }
mint(ll x = 0) : x((x % mod + mod) % mod) { assert(mod > 0); }
constexpr int val() const { return x; }
mint &operator+=(const mint &a) {
if ((x += a.val()) >= mod) x -= mod;
return *this;
}
mint &operator-=(const mint &a) {
if ((x += mod - a.val()) >= mod) x -= mod;
return *this;
}
mint &operator*=(const mint &a) {
(x *= a.val()) %= mod;
return *this;
}
mint operator+(const mint &a) const {
mint res(*this);
return res += a;
}
mint operator-(const mint &a) const {
mint res(*this);
return res -= a;
}
mint operator*(const mint &a) const {
mint res(*this);
return res *= a;
}
mint pow(ll t) const {
mint res = 1, a(*this);
while (t > 0) {
if (t & 1) res *= a;
t >>= 1;
a *= a;
}
return res;
}
mint inv() const { return pow(mod - 2); }
};
int mint::mod = 0;
using vm = vector<mint>;
vm karatsuba(const vm &f, const vm &g) {
int n = SZ(f);
int m = SZ(g);
if (!n or !m) return {};
if (min(n, m) <= 40) {
vm res(n + m - 1);
rep(i, n) rep(j, m) res[i + j] += f[i] * g[j];
return res;
}
int a = max(n, m) / 2;
vm f0(f.begin(), f.begin() + min(a, n));
vm f1(f.begin() + min(a, n), f.end());
vm g0(g.begin(), g.begin() + min(a, m));
vm g1(g.begin() + min(a, m), g.end());
vm h0 = karatsuba(f0, g0);
vm h2 = karatsuba(f1, g1);
vm h1;
{
vm df(max(SZ(f0), SZ(f1)));
rep(i, SZ(f0)) df[i] += f0[i];
rep(i, SZ(f1)) df[i] -= f1[i];
vm dg(max(SZ(g0), SZ(g1)));
rep(i, SZ(g0)) dg[i] -= g0[i];
rep(i, SZ(g1)) dg[i] += g1[i];
h1 = karatsuba(df, dg);
}
if (SZ(h1) < max(SZ(h0), SZ(h2))) h1.resize(max(SZ(h0), SZ(h2)));
rep(i, SZ(h0)) h1[i] += h0[i];
rep(i, SZ(h2)) h1[i] += h2[i];
vm res(n + m - 1);
rep(i, SZ(h0)) res[i] += h0[i];
rep(i, SZ(h1)) res[i + a] += h1[i];
rep(i, SZ(h2)) res[i + a * 2] += h2[i];
return res;
}
int main() {
int n, p;
cin >> n >> p;
mint::set_mod(p);
vm fact(2 * n + 10, 1);
vm ifact(2 * n + 10);
rep2(i, 1, SZ(fact)) fact[i] = fact[i - 1] * i;
ifact.back() = fact.back().inv();
rrep(i, SZ(fact) - 1) ifact[i] = ifact[i + 1] * (i + 1);
// A : æ£ã—ã„貪欲ã§é¸ã¶åŒºé–“ã®é›†åˆã€€B : 嘘貪欲ã§é¸ã¶åŒºé–“ã®é›†åˆ
// |A| = |B| ã®ã‚‚ã®ã‚’æ•°ãˆã‚‹
// A, B ã«å«ã¾ã‚Œã‚‹åŒºé–“を後ã‚ã‹ã‚‰ 1 組ãšã¤åŠ ãˆã¦ã„ã (é–“ã«ã‚る区間もåŒæ™‚ã«åŠ ãˆã‚‹)
// dp[i][j]
// i : åŠ ãˆãŸåŒºé–“ã®å€‹æ•°
// j : A, B ã«å«ã¾ã‚Œã‚‹åŒºé–“ã®ã†ã¡æœ€å¾Œã«åŠ ãˆãŸçµ„ãŒåˆ¥ã€…ã®åŒºé–“ã‹ã©ã†ã‹
vector dp(n + 1, vm(2));
dp[1][0] = 1;
if (n >= 2) dp[2][1] = 1;
// O(N^2) ã§ã® DP (subtask 5)
// rep2(i, 1, n + 1) {
// // 0 -> 0
// if (i + 1 <= n) {
// mint now = dp[i][0];
// rep(j, n - i) {
// dp[i + 1 + j][0] += now;
// now *= 2 * i - 1 + j;
// }
// }
// // 0 -> 1
// if (i + 2 <= n) {
// mint now = dp[i][0];
// rep(j, n - i - 1) {
// dp[i + 2 + j][1] += now * (j + 1);
// now *= 2 * i - 1 + j;
// }
// }
// // 1 -> 0
// if (i + 1 <= n) {
// mint now = dp[i][1];
// rep(j, n - i) {
// dp[i + 1 + j][0] += now * (j + 1);
// now *= 2 * i - 2 + j;
// }
// }
// // 1 -> 1
// if (i + 2 <= n) {
// mint now = dp[i][1];
// rep(j, n - i - 1) {
// dp[i + 2 + j][1] += now * (j + 2) * (j + 1);
// now *= 2 * i - 2 + j;
// }
// }
// }
// O(N^1.59) ã§ã® DP (満点解)
// [l, m) ã‹ã‚‰ [m, r) ã¸ã®é·ç§»ã‚’ã¾ã¨ã‚ã¦è¡Œã†
auto induce = [&](int l, int m, int r) -> void {
vm f(m - l), g(r - l - 1);
// 0 -> 0
{
rep2(i, l, m) f[m - 1 - i] = dp[i][0] * ifact[2 * i - 2];
rep2(i, l + m, m + r - 1) g[i - (l + m)] = fact[i - 3];
vm h = karatsuba(f, g);
rep2(i, m, r) dp[i][0] += h[m - l - 1 + i - m];
}
// 0 -> 1
if (m - l >= 2) {
rep2(i, l, m - 1) f[m - 1 - i] = dp[i][0] * ifact[2 * i - 2];
f[0] = 0;
rep2(i, l + m, m + r - 1) g[i - (l + m)] = fact[i - 4];
vm h = karatsuba(f, g);
rep2(i, m, r) dp[i][1] += h[m - l - 1 + i - m] * (i - 1);
rep2(i, l, m - 1) f[m - 1 - i] *= -i;
h = karatsuba(f, g);
rep2(i, m, r) dp[i][1] += h[m - l - 1 + i - m];
}
{
int i = m - 1;
rep2(j, m + 1, r) {
dp[j][1] += dp[i][0] * (j - i - 1) * fact[i + j - 4] * ifact[2 * i - 2];
}
}
// 1 -> 0
{
rep2(i, l, m) f[m - 1 - i] = dp[i][1] * (i >= 2 ? ifact[2 * i - 3] : 0);
rep2(i, l + m, m + r - 1) g[i - (l + m)] = (i >= 4 ? fact[i - 4] : 0);
vm h = karatsuba(f, g);
rep2(i, m, r) dp[i][0] += h[m - l - 1 + i - m] * i;
rep2(i, l, m) f[m - 1 - i] *= -i;
h = karatsuba(f, g);
rep2(i, m, r) dp[i][0] += h[m - l - 1 + i - m];
}
// 1 -> 1
if (m - l >= 2) {
rep2(i, l, m - 1) f[m - 1 - i] = dp[i][1] * (i >= 2 ? ifact[2 * i - 3] : 0);
f[0] = 0;
rep2(i, l + m, m + r - 1) g[i - (l + m)] = (i >= 5 ? fact[i - 5] : 0);
vm h = karatsuba(f, g);
rep2(i, m, r) dp[i][1] += h[m - l - 1 + i - m] * i * (i - 1);
rep2(i, l, m - 1) f[m - 1 - i] *= i;
h = karatsuba(f, g);
rep2(i, m, r) dp[i][1] += h[m - l - 1 + i - m] * (-2 * i);
rep2(i, l, m - 1) f[m - 1 - i] *= i + 1;
h = karatsuba(f, g);
rep2(i, m, r) dp[i][1] += h[m - l - 1 + i - m];
}
{
int i = m - 1;
rep2(j, m + 1, r) {
dp[j][1] += dp[i][1] * (j * (j - 1) - 2 * i * j + i * (i + 1)) * fact[i + j - 5] * ifact[2 * i - 3];
}
}
};
auto solve = [&](auto &solve, int l, int r) -> void {
assert(l < r);
if (r - l == 1) return;
int m = (l + r) / 2;
solve(solve, l, m);
induce(l, m, r);
solve(solve, m, r);
};
solve(solve, 1, n + 1);
mint ans = 1;
rep(i, n) ans *= 2 * i + 1;
rep2(i, 1, n + 1) {
ans -= dp[i][0] * fact[n + i - 2] * ifact[2 * i - 2];
if (i >= 2) ans -= dp[i][1] * (n - i + 1) * fact[n + i - 3] * ifact[2 * i - 3];
}
cout << ans.val() << endl;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |