1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
#define FOR(i,l,r)for(int i=(l);i<=(r);++i)
#define REP(i,n)FOR(i,0,(n)-1)
#define ssize(x)int(x.size())
#ifdef DEBUG
auto operator<<(auto&o,auto x)->decltype(x.end(),o);
auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";}
auto&operator<<(auto&o,tuple<auto,auto,auto>t){return o<<"("<<get<0>(t)<<", "<<get<1>(t)<<", "<<get<2>(t)<<")";}
auto&operator<<(auto&o,tuple<auto,auto,auto,auto>t){return o<<"("<<get<0>(t)<<", "<<get<1>(t)<<", "<<get<2>(t)<<", "<<get<3>(t)<<")";}
auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";}
#define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X)
#else
#define debug(...){}
#endif

int mod;
int add(int a, int b) {
	a += b;
	return a >= mod ? a - mod : a;
}
int sub(int a, int b) {
	return add(a, mod - b);
}
int mul(int a, int b) {
	return int(a * LL(b) % mod);
}
int powi(int a, int b) {
	for(int ret = 1;; b /= 2) {
		if(b == 0)
			return ret;
		if(b & 1)
			ret = mul(ret, a);
		a = mul(a, a);
	}
}
int inv(int x) {
	return powi(x, mod - 2);
}
int factorial(int n) {
	int ret = 1;
	FOR(i, 1, n)
		ret = mul(ret, i);
	return ret;
}

int hook(int a, int b, int c) {
	vector<int> lowest(b), rightmost(a);
	int n = 0;
	REP(i, a) {
		REP(j, b) {
			if (abs(a - i) + abs(b - j) > a + b - c) {
				++n;
				lowest[j] = max(lowest[j], i);
				rightmost[i] = max(rightmost[i], j);
			}
		}
	}
	const int nom = factorial(n);
	int denom = 1;
	REP(i, a) {
		REP(j, b) {
			if (abs(a - i) + abs(b - j) > a + b - c) {
				int cnt = 1;
				cnt += lowest[j] - i;
				cnt += rightmost[i] - j;
				denom = mul(denom, cnt);
			}
		}
	}
	const auto ret = mul(nom, inv(denom));
	return ret;
}

int shifted_hook(int a, int b, int c) {
	vector<int> lowest(c), rightmost(a);
	int n = 0;
	REP(i, a) {
		REP(j, c) {
			if (i <= j and abs(a - i) + abs(c - j) > c - b + 1) {
				++n;
				lowest[j] = max(lowest[j], i);
				rightmost[i] = max(rightmost[i], j);
			}
		}
	}
	const int nom = factorial(n);
	int denom = 1;
	REP(i, a) {
		REP(j, c) {
			if (i <= j and abs(a - i) + abs(c - j) > c - b + 1) {
				int cnt = 1;
				cnt += lowest[j] - i;
				cnt += rightmost[i] - j;
				if (j + 1 < a)
					cnt += rightmost[j + 1] - j;
				denom = mul(denom, cnt);
			}
		}
	}
	const auto ret = mul(nom, inv(denom));
	return ret;
}

void solve() {
	int a, b, c;
	cin >> a >> b >> c >> mod;

	const int n = a * b - (a + b - c) * (a + b - c - 1) / 2;
	const int cnt = mul(hook(a, b, c), shifted_hook(a, b, c));

#ifdef TESTS
	cout << add(n, cnt) << '\n';
#else
	cout << n << ' ' << cnt << '\n';
#endif
	return;
}

int main() {
	cin.tie(0)->sync_with_stdio(0);

	solve();
}