Submission #793155

#TimeUsernameProblemLanguageResultExecution timeMemory
793155JohannFestivals in JOI Kingdom 2 (JOI23_festival2)C++14
87 / 100
772 ms306640 KiB
#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef pair<ll, ll> pii;
pii operator+(const pii &a, const pii &b) { return {a.first + b.first, a.second + b.second}; }
typedef vector<pii> vpii;
typedef vector<vpii> vvpii;
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()

ll N, P;
int dp[6001][3001][8]; // pos, brackets opened and usable by opt, flag with 6 states
// states: 00x no bracket for bad
//         01x bracket for bad but not usable by opt
//         10x undefined...
//         11x bracket for bad and usable by opt
// if x == 0: both have the same score, x == 1: optimal is one better
vi fac, facinv;

ll fast_exp(ll base, ll exp, ll MOD)
{
    ll ans = 1;
    while (exp > 0)
    {
        if (exp & 1)
            ans = (ans * base) % MOD;
        base = (base * base) % MOD;
        exp >>= 1;
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> N >> P;

    fac.resize(2 * N + 3);
    facinv.resize(sz(fac));
    fac[0] = 1;
    facinv[0] = 1;
    for (ll i = 1; i < sz(fac); ++i)
    {
        fac[i] = (fac[i - 1] * i) % P;
        facinv[i] = fast_exp(fac[i], P - 2, P);
    }

    int dim1 = 2 * N + 1, dim2 = N + 1, dim3 = 8;
    // dp.assign(dim1, vvi(dim2, vi(dim3, 0)));
    // int dpp[2 * N + 1][N + 1][8];
    // for (int pos = 0; pos < sz(dp); ++pos)
    // dp[pos].assign(dim2, vi(dim3, 0));
    dp[0][0][0] = 1;
    for (int pos = 0; pos < 2 * N; ++pos)
    {
        int space = 2 * N - pos;
        for (int bropt = 0; bropt < dim2 && pos + bropt <= 2 * N; ++bropt)
        {
            for (int st = 0; st < dim3; ++st)
            {
                if (dp[pos][bropt][st] == 0)
                    continue;

                bool optBetter = st & 1;
                bool bracketForBad = st & 2;
                bool bracketUsableForOpt = st & 4;

                if (!bracketForBad && bracketUsableForOpt)
                    continue;

                ll dpvalue = dp[pos][bropt][st];
                ll newdpvalue;

                // open bracket
                if (bropt < dim2 - 1)
                {
                    int nst = st;
                    if (!bracketForBad)
                        nst |= 0b110;
                    dp[pos + 1][bropt + 1][nst] = (dpvalue + dp[pos + 1][bropt + 1][nst]) % P;
                }

                // close bracket
                if (bropt == 0 && !bracketForBad)
                    continue;

                if (bracketForBad)
                {
                    if (bracketUsableForOpt)
                    {
                        assert(bropt > 0);

                        // closing both
                        newdpvalue = dpvalue;
                        newdpvalue = (newdpvalue * fac[space - 1]) % P;
                        newdpvalue = (newdpvalue * facinv[space - bropt]) % P;
                        dp[pos + bropt][0][optBetter] = (newdpvalue + dp[pos + bropt][0][optBetter]) % P;

                        // closing opt and all others apart from bad
                        if (!optBetter)
                        {
                            newdpvalue = (dpvalue * (bropt - 1)) % P;
                            newdpvalue = (newdpvalue * fac[space - 1]) % P;
                            newdpvalue = (newdpvalue * facinv[space - bropt + 1]) % P;
                            int nst = 0b011; // bracket for bad by default true
                            dp[pos + bropt - 1][0][nst] = (newdpvalue + dp[pos + bropt - 1][0][nst]) % P;
                        }
                    }
                    else // bracket not usable for opt
                    {
                        // closing only bad
                        assert(optBetter);
                        int nst = 0;
                        dp[pos + 1][bropt][nst] = (dpvalue + dp[pos + 1][bropt][nst]) % P;

                        // closing only opt
                        // well because of the assert this cannot happen...
                    }
                }
                else
                {
                    if (!optBetter)
                    {
                        int nst = 1; // bracket for bad by default false
                        newdpvalue = dpvalue;
                        newdpvalue = (newdpvalue * bropt) % P;
                        newdpvalue = (newdpvalue * fac[space - 1]) % P;
                        newdpvalue = (newdpvalue * facinv[space - bropt]) % P;
                        dp[pos + bropt][0][nst] = (newdpvalue + dp[pos + bropt][0][nst]) % P;
                    }
                }
            }
        }
    }

    ll ans = 1;
    for (ll i = 1; i < 2 * N; i += 2)
        ans = (ans * i) % P;

    ans = (ans - dp[2 * N][0][0] + P) % P;

    cout << ans << "\n";

    return 0;
}

Compilation message (stderr)

festival2.cpp: In function 'int main()':
festival2.cpp:54:9: warning: unused variable 'dim1' [-Wunused-variable]
   54 |     int dim1 = 2 * N + 1, dim2 = N + 1, dim3 = 8;
      |         ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...