Problem: For each of the K^{NM} ways to write an integer between 1 and K (inclusive) in every square in a square grid with N rows and M columns, find the value defined below, then compute the sum of all those K^{NM} values, modulo D.

* For each of the NM squares, find the minimum among the N+M-1 integers written in the square's row or the square's column. The value defined for the grid is the product of all these NM values.

Constraints

* 1 \leq N,M,K \leq 100
* 10^8 \leq D \leq 10^9
* N,M,K, and D are integers.
* D is prime.

Input

Input is given from Standard Input in the following format:


N M K D


Output

Print the sum of the K^{NM} values, modulo D.

Examples

Input

2 2 2 998244353


Output

35


Input

2 3 4 998244353


Output

127090


Input

31 41 59 998244353


Output

827794103

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 105;

inline int gi()
{
	char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	int sum = 0;
	while ('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

int mod;
inline int add(int x, int y) {return x + y > mod ? x + y - mod : x + y;}
inline int sub(int x, int y) {return x < y ? x - y + mod : x - y;}
inline void inc(int &x, int y) {x += y; if (x >= mod) x -= mod;}
inline void dec(int &x, int y) {x -= y; if (x < 0) x += mod;} 

int n, m, t;
int c[maxn][maxn], pw[maxn][maxn * maxn], f[2][maxn][maxn], tr[maxn][maxn];

void init()
{
	for (int i = 0; i <= n; ++i)
		for (int j = c[i][0] = 1; j <= i; ++j)
			c[i][j] = add(c[i - 1][j - 1], c[i - 1][j]);
	for (int i = 0; i <= t; ++i)
		for (int j = pw[i][0] = 1; j <= n * m; ++j) pw[i][j] = (ll)pw[i][j - 1] * i % mod;
}

int main()
{
	n = gi(); m = gi(); t = gi(); mod = gi();
	if (n < m) swap(n, m);
	init();

	int cur = 0;
	f[0][0][0] = 1;
	for (int k = 1; k <= t; ++k) {
		cur ^= 1; memset(f[cur], 0, sizeof(f[cur]));
		for (int j = 0; j <= m; ++j)
			for (int i = 0; i <= n; ++i) tr[j][i] = (ll)pw[k][i * (m - j)] * pw[t - k + 1][i * j] % mod;
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= m; ++j)
				if (f[cur ^ 1][i][j]) {
					for (int l = 0; l + i <= n; ++l)
						f[cur][i + l][j] = (f[cur][i + l][j] + (ll)f[cur ^ 1][i][j] * c[i + l][i] % mod * tr[j][l]) % mod;
				}
		cur ^= 1; memset(f[cur], 0, sizeof(f[cur]));
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= m; ++j) tr[i][j] = (ll)pw[k][j * (n - i)] * pw[t - k + 1][i * j] % mod;
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= m; ++j)
				if (f[cur ^ 1][i][j]) {
					for (int l = 0; l + j <= m; ++l)
						f[cur][i][j + l] = (f[cur][i][j + l] + (ll)f[cur ^ 1][i][j] * c[j + l][j] % mod * tr[i][l]) % mod;
				}
		cur ^= 1; memset(f[cur], 0, sizeof(f[cur]));
		for (int j = 0; j <= m; ++j)
			for (int i = 0; i <= n; ++i) tr[j][i] = (ll)pw[k][i * (m - j)] * pw[t - k][i * j] % mod;
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= m; ++j)
				if (f[cur ^ 1][i][j]) {
					for (int l = 0; l + i <= n; ++l)
						if (~l & 1) f[cur][i + l][j] = (f[cur][i + l][j] + (ll)f[cur ^ 1][i][j] * c[i + l][i] % mod * tr[j][l]) % mod;
						else f[cur][i + l][j] = (f[cur][i + l][j] + (ll)(mod - f[cur ^ 1][i][j]) * c[i + l][i] % mod * tr[j][l]) % mod;
				}
		cur ^= 1; memset(f[cur], 0, sizeof(f[cur]));
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= m; ++j) tr[i][j] = (ll)pw[k][j * (n - i)] * pw[t - k][i * j] % mod;
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= m; ++j)
				if (f[cur ^ 1][i][j]) {
					for (int l = 0; l + j <= m; ++l)
						if (~l & 1) f[cur][i][j + l] = (f[cur][i][j + l] +  (ll)f[cur ^ 1][i][j] * c[j + l][j] % mod * tr[i][l]) % mod;
						else f[cur][i][j + l] = (f[cur][i][j + l] + (ll)(mod - f[cur ^ 1][i][j]) * c[j + l][j] % mod * tr[i][l]) % mod;
				}
	}
	printf("%d\n", f[cur][n][m]);
	
	return 0;
}