#include namespace { #pragma GCC diagnostic ignored "-Wunused-function" #include #pragma GCC diagnostic warning "-Wunused-function" using namespace std; using namespace atcoder; #define rep(i,n) for(int i = 0; i < (int)(n); i++) #define rrep(i,n) for(int i = (int)(n) - 1; i >= 0; i--) #define all(x) begin(x), end(x) #define rall(x) rbegin(x), rend(x) template bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; } template bool chmin(T& a, const T& b) { if (b < a) { a = b; return true; } else return false; } using ll = long long; using P = pair; using VI = vector; using VVI = vector; using VL = vector; using VVL = vector; using mint = modint; const int di[] = {1, 0, -1, 0}; const int dj[] = {0, 1, 0, -1}; mint comb[30][30], fact[30], inv[30], pow2[30]; } int main() { ios::sync_with_stdio(false); cin.tie(0); int h, w, m; ll k; cin >> h >> w >> k >> m; mint::set_mod(m); comb[0][0] = 1; rep(i, 29) rep(j, i + 1) comb[i+1][j] += comb[i][j], comb[i+1][j+1] += comb[i][j]; fact[0] = pow2[0] = 1; for (int i = 1; i < 30; i++) fact[i] = fact[i-1] * i, inv[i] = mint(i).inv(), pow2[i] = pow2[i-1] * 2; vector> st; bool seen[25][25]{}; int dist[26][26]{}; rep(i0, h) rep(j0, w) { auto dfs = [&](auto&& self, int use, int unuse) -> void { if (st.empty()) { dist[use][unuse]++; return; } auto [i, j, k] = st.back(); st.pop_back(); if (k < 4) { int ni = i + di[k], nj = j + dj[k]; st.emplace_back(i, j, k + 1); if (0 <= ni && ni < h && 0 <= nj && nj < w && !seen[ni][nj]) { if (pair(i0, j0) < pair(ni, nj)) { st.emplace_back(ni, nj, 0); seen[ni][nj] = true; self(self, use + 1, unuse); seen[ni][nj] = false; st.pop_back(); } seen[ni][nj] = true; self(self, use, unuse + 1); seen[ni][nj] = false; } else { self(self, use, unuse); } st.pop_back(); } else { self(self, use, unuse); } st.emplace_back(i, j, k); }; st.emplace_back(i0, j0, 0); seen[i0][j0] = true; dfs(dfs, 1, 0); seen[i0][j0] = false; assert(st.size() == 1); st.pop_back(); } mint ans; rep(use, 26) rep(unuse, 26) if (dist[use][unuse]) ans += mint(use).pow(k) * dist[use][unuse] * pow2[h * w - use - unuse]; ans /= pow2[h * w]; mint c; for (int i = 1; i <= h * w; i++) c += inv[i]; ans *= c; cout << ans.val() << '\n'; exit(0); rep(use, 26) { mint cnt; rep(unuse, 26) if (dist[use][unuse]) for (int chose = use; chose <= h * w; chose++) { // cout << use << ' '<< unuse << endl; int free_area = h * w - use - unuse; int rest = chose - use; for (int cf = 0; cf <= rest; cf++) { int cu = rest - cf; if (cf <= free_area && cu <= unuse) { cnt += dist[use][unuse] * comb[free_area][cf] * pow2[cf] * comb[unuse][cu] * fact[chose] * fact[h * w - chose] * inv[h * w - chose + 1]; } } } if (cnt.val()) cout << use << ' ' << cnt.val() << endl; ans += cnt * mint(use).pow(k); } ans /= fact[h * w] * mint(2).pow(h * w); cout << ans.val() << '\n'; // int acc = 0; // rep(i, 26) rep(j, 26) acc += dist[i][j]; // cout << acc << endl; // for (int h = 1; h <= 25; h++) { // for (int w = h; h * w <= 25; w++) { // int valid_cnt = 0; // bool g[25][25]; // vector

st; // int dist[26]{}; // rep(s, 1 << h * w) if (s) { // rep(i, h) rep(j, w) g[i][j] = s >> i * w + j & 1; // int sv = countr_zero(0U + s); // int i0 = sv / w, j0 = sv % w; // st.emplace_back(i0, j0); // g[i0][j0] = 0; // while (st.size()) { // auto [i, j] = st.back(); st.pop_back(); // auto idxchk = [&](int i, int j) { return 0 <= i && i < h && 0 <= j && j < w; }; // rep(k, 4) { // int ni = i + di[k], nj = j + dj[k]; // if (!idxchk(ni, nj) || !g[ni][nj]) continue; // g[ni][nj] = 0; // st.emplace_back(ni, nj); // } // } // if ([&]() { // rep(i, h) rep(j, w) if (g[i][j]) return false; // return true; // }()) { // dist[popcount(0U + s)]++; // } // } // // cout << '{'; // // rep(i, 26) cout << dist[i] << ",}"[i == 25]; // // cout << ','; // cout << h << ' ' << w << ' ' << accumulate(all(dist), 0) << endl; // } // } }