Submission #248834

#TimeUsernameProblemLanguageResultExecution timeMemory
248834srvltEnergetic turtle (IZhO11_turtle)C++14
100 / 100
214 ms9976 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace std; using namespace __gnu_pbds; #define ll long long #define ld long double #define pb push_back #define all(x) (x).begin(), (x).end() #define SZ(x) (int)(x).size() template <typename T> using ord_set = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); constexpr int n0 = 6e5 + 123, k0 = 23, m0 = 50000; int n, m, k, t, z, f[k0], cf[k0], ways[k0][k0], g[n0], fact[11][n0], phi; array <int, 2> p[k0]; vector <int> F; int bp(int x, int y, int mod) { int res = 1; while (y) { if (y & 1) res = (ll)res * x % mod; x = (ll)x * x % mod; y /= 2; } return res; } int binomial(int x, int y) { if (y > x) return 0; int res = 1; for (int i = 1; i <= SZ(F); i++) { int pw = fact[i][x] - fact[i][y] - fact[i][x - y]; if (pw > 0) { res = (ll)res * bp(F[i - 1], pw, z) % z; } else { res = (ll)res * bp(bp(F[i - 1], phi - 1, z), pw, z) % z; } } res = (((ll)res * fact[0][x] % z) * bp(fact[0][y], phi - 1, z) % z) * bp(fact[0][x - y], phi - 1, z) % z; return res; } int main() { ios_base::sync_with_stdio(false), cin.tie(NULL); #ifdef LOCAL freopen("input.txt", "r", stdin); #endif cin >> n >> m >> k >> t >> z; if (z == 1) return cout << 0, 0; vector <bool> prime(m0, true); prime[0] = prime[1] = false; vector <int> primes; for (int i = 2; i < m0; i++) { if (prime[i]) primes.pb(i); for (int j : primes) { if ((ll)i * j >= m0) break; prime[i * j] = false; if (i % j == 0) break; } } int Z = z; for (int p : primes) { if (p > Z) break; int res = 0; while (Z % p == 0) Z /= p, res++; if (res) F.pb(p); } if (Z > 1) F.pb(Z); int A = 1, B = 1; for (int i : F) A *= (i - 1), B *= i; phi = (z / B) * A; for (int i = 1; i < n0; i++) { int x = i; while (true) { int G = __gcd(x, z); if (G == 1) break; x /= G; } g[i] = x; } for (int i = 0; i <= SZ(F); i++) { if (i == 0) { fact[i][0] = 1; for (int j = 1; j < n0; j++) fact[i][j] = (ll)fact[i][j - 1] * g[j] % z; } else { for (int j = 1; j < n0; j++) { int res = 0, x = j; while (x % F[i - 1] == 0) x /= F[i - 1], res++; fact[i][j] = fact[i][j - 1] + res; } } } for (int i = 0; i < k; i++) cin >> p[i][0] >> p[i][1]; sort(p, p + k); for (int i = 0; i <= k + 1; i++) { for (int j = i + 1; j <= k + 1; j++) { int x = 0, y = 0, x2 = n, y2 = m; if (i > 0) x = p[i - 1][0], y = p[i - 1][1]; if (j < k + 1) x2 = p[j - 1][0], y2 = p[j - 1][1]; ways[i][j] = binomial(x2 - x + y2 - y, x2 - x); } } for (int mask = 1; mask < (1 << k); mask++) { int bad = 0, res = 1, last = -1; int b = __builtin_popcount(mask); for (int i = 0; i < k; i++) { if (mask >> i & 1) { if (last != -1 && p[i][1] < p[last][1]) { bad = 1; break; } if (last == -1) res = (ll)res * ways[0][i + 1] % z; else res = (ll)res * ways[last + 1][i + 1] % z; last = i; } } if (bad) continue; res = (ll)res * ways[last + 1][k + 1] % z; f[b] = (f[b] + res) % z; } int res = ways[0][k + 1]; for (int i = t + 1; i <= k; i++) { int cur = 0; for (int j = t + 1; j < i; j++) cur = (cur + (ll)binomial(i, j) * cf[j] % z) % z; cf[i] = (z - 1) - cur; res = (res + (ll)cf[i] * f[i] % z) % z; } cout << res; }
#Verdict Execution timeMemoryGrader output
Fetching results...