Problem:
Score : 2000 points

Problem Statement

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.

Sample Input 1

2 2 2 998244353

Sample Output 1

35

We have 1 way to write integers such that the product of the NM values is 16, 4 ways such that the product is 2, and 11 ways such that the product is 1.

Sample Input 2

2 3 4 998244353

Sample Output 2

127090

Sample Input 3

31 41 59 998244353

Sample Output 3

827794103

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

/*====Corycle====*/
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N=105;
int read(){
	int s=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
	return s*f;
}
int n,m,K,Mod;
int C[N][N],P[N][N],f[2][N][N];
int mod(int x){return x>=Mod?x-Mod:x;}
void Prepare(){
	for(int i=0;i<N;i++){C[i][0]=1;for(int j=1;j<=i;j++)C[i][j]=mod(C[i-1][j-1]+C[i-1][j]);}
	for(int i=0;i<N;i++){P[i][0]=1;for(int j=1;j<N;j++)P[i][j]=1ll*P[i][j-1]*i%Mod;}
}
void Clear(int t){for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)f[t][i][j]=0;}
int main(){
//	freopen("_.in","r",stdin);
//	freopen("_.out","w",stdout);
	n=read();m=read();K=read();Mod=read();Prepare();
	int t=0;f[t][0][0]=1;
	for(int T=1;T<=K;T++){
		Clear(t^=1);
		for(int i=0;i<=n;i++){
			for(int j=0;j<=m;j++){
				if(!f[t^1][i][j])continue;
				int tmp=f[t^1][i][j],mul=1ll*P[T][m-j]*P[K-T+1][j]%Mod;
				for(int a=0;i+a<=n;a++,tmp=1ll*tmp*mul%Mod){
					f[t][i+a][j]=(f[t][i+a][j]+1ll*C[n-i][a]*tmp)%Mod;
				}
			}
		}
		Clear(t^=1);
		for(int i=0;i<=n;i++){
			for(int j=0;j<=m;j++){
				if(!f[t^1][i][j])continue;
				int tmp=f[t^1][i][j],mul=1ll*P[T][n-i]*P[K-T+1][i]%Mod;
				for(int b=0;j+b<=m;b++,tmp=1ll*tmp*mul%Mod){
					f[t][i][j+b]=(f[t][i][j+b]+1ll*C[m-j][b]*tmp)%Mod;
				}
			}
		}
		Clear(t^=1);
		for(int i=0;i<=n;i++){
			for(int j=0;j<=m;j++){
				if(!f[t^1][i][j])continue;
				int tmp=f[t^1][i][j],mul=1ll*P[T][m-j]*(Mod-P[K-T][j])%Mod;
				for(int c=0;i+c<=n;c++,tmp=1ll*tmp*mul%Mod){
					f[t][i+c][j]=(f[t][i+c][j]+1ll*C[n-i][c]*tmp)%Mod;
				}
			}
		}
		Clear(t^=1);
		for(int i=0;i<=n;i++){
			for(int j=0;j<=m;j++){
				if(!f[t^1][i][j])continue;
				int tmp=f[t^1][i][j],mul=1ll*P[T][n-i]*(Mod-P[K-T][i])%Mod;
				for(int d=0;j+d<=m;d++,tmp=1ll*tmp*mul%Mod){
					f[t][i][j+d]=(f[t][i][j+d]+1ll*C[m-j][d]*tmp)%Mod;
				}
			}
		}
	}
	printf("%d",f[t][n][m]);
	return 0;
}