#include <bits/stdc++.h>
using namespace std;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
*this << "[";
for (auto it = d.b; it != d.e; ++it)
*this << ", " + 2 * (it == d.b) << *it;
ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
// debug & operator << (debug & dd, P p) { dd << "(" << p.x << ", " << p.y << ")"; return dd; }
int mod;
void add_self(int& a, int b) {
a += b;
if(a >= mod) {
a -= mod;
}
}
int main() {
int w, h;
scanf("%d%d%d", &w, &h, &mod);
// h = 10'000'000 / w;
if(h == 1) {
puts("1");
return 0;
}
vector<vector<int>> bottom(2, vector<int>(h));
vector<vector<int>> middle(2, vector<int>(h));
int cur = 0;
for(int i = 0; i < h; ++i) {
bottom[0][i] = 1;
}
for(int who = 0; who < w - 1; ++who) {
for(int i = 0; i < h; ++i) {
bottom[cur^1][i] = middle[cur^1][i] = 0;
}
// bottom -> bottom
int pref = 0;
for(int i = 0; i < h; ++i) {
add_self(pref, bottom[cur][i]);
// pref += bottom[who][i];
bottom[cur^1][i] = (bottom[cur^1][i] + (long long) pref * (h - i)) % mod;
// bottom[who+1][i] += pref * (h - i);
}
// bottom -> middle
for(int i = 0; i < h; ++i) {
middle[cur^1][i] = (middle[cur^1][i] + (long long) bottom[cur][i] * (h - i)) % mod;
// middle[who+1][i] += bottom[who][i] * (h - i);
}
// middle -> bottom
pref = 0;
for(int i = 0; i < h; ++i) {
// pref += middle[who][i] * i;
pref = (pref + (long long) middle[cur][i] * i) % mod;
// bottom[who+1][i] += pref * (h - i);
bottom[cur^1][i] = (bottom[cur^1][i] + (long long) pref * (h - i)) % mod;
}
pref = 0;
for(int i = h - 1; i >= 0; --i) {
// bottom[who+1][i] += pref * (i + 1);
bottom[cur^1][i] = (bottom[cur^1][i] + (long long) pref * (i + 1)) % mod;
// pref += middle[who][i] * (h - i); // actually, suffix
pref = (pref + (long long) middle[cur][i] * (h - i)) % mod;
}
// middle -> middle
pref = 0;
for(int i = h - 1; i >= 0; --i) {
// middle[who+1][i] += pref;
add_self(middle[cur^1][i], pref);
pref = (pref + (long long) middle[cur][i] * (h - i)) % mod;
// pref += middle[who][i] * (h - i); // actually, suffix
}
// for(int i = 0; i < h; ++i) {
// for(int j = i; j < h; ++j) {
// bottom[who+1][j] += bottom[who][i] * (h - j);
// }
// middle[who+1][i] += bottom[who][i] * (h - i);
// middle -> bottom
// for(int j = 0; j < i; ++j) {
// bottom[who+1][j] += middle[who][i] * (h - i) * (j + 1);
// }
// for(int j = i; j < h; ++j) {
// bottom[who+1][j] += middle[who][i] * i * (h - j);
// }
// middle -> middle
// for(int j = 0; j < i; ++j) {
// middle[who+1][j] += middle[who][i] * (h - i) * 1;
// }
// }
cur ^= 1;
}
long long answer = 0;
for(int i = 0; i < h; ++i) {
answer = (answer + (long long) bottom[cur][i] * (h - i) + (long long) middle[cur][i] * i % mod * (h - i)) % mod;
// answer += (long long) bottom[w-1][i] * (h - i);
// answer += (long long) middle[w-1][i] * i * (h - i);
}
printf("%lld\n", answer % mod);
}
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; #define sim template < class c #define ris return * this #define dor > debug & operator << #define eni(x) sim > typename \ enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) { sim > struct rge { c b, e; }; sim > rge<c> range(c i, c j) { return rge<c>{i, j}; } sim > auto dud(c* x) -> decltype(cerr << *x, 0); sim > char dud(...); struct debug { #ifdef LOCAL ~debug() { cerr << endl; } eni(!=) cerr << boolalpha << i; ris; } eni(==) ris << range(begin(i), end(i)); } sim, class b dor(pair < b, c > d) { ris << "(" << d.first << ", " << d.second << ")"; } sim dor(rge<c> d) { *this << "["; for (auto it = d.b; it != d.e; ++it) *this << ", " + 2 * (it == d.b) << *it; ris << "]"; } #else sim dor(const c&) { ris; } #endif }; #define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] " // debug & operator << (debug & dd, P p) { dd << "(" << p.x << ", " << p.y << ")"; return dd; } int mod; void add_self(int& a, int b) { a += b; if(a >= mod) { a -= mod; } } int main() { int w, h; scanf("%d%d%d", &w, &h, &mod); // h = 10'000'000 / w; if(h == 1) { puts("1"); return 0; } vector<vector<int>> bottom(2, vector<int>(h)); vector<vector<int>> middle(2, vector<int>(h)); int cur = 0; for(int i = 0; i < h; ++i) { bottom[0][i] = 1; } for(int who = 0; who < w - 1; ++who) { for(int i = 0; i < h; ++i) { bottom[cur^1][i] = middle[cur^1][i] = 0; } // bottom -> bottom int pref = 0; for(int i = 0; i < h; ++i) { add_self(pref, bottom[cur][i]); // pref += bottom[who][i]; bottom[cur^1][i] = (bottom[cur^1][i] + (long long) pref * (h - i)) % mod; // bottom[who+1][i] += pref * (h - i); } // bottom -> middle for(int i = 0; i < h; ++i) { middle[cur^1][i] = (middle[cur^1][i] + (long long) bottom[cur][i] * (h - i)) % mod; // middle[who+1][i] += bottom[who][i] * (h - i); } // middle -> bottom pref = 0; for(int i = 0; i < h; ++i) { // pref += middle[who][i] * i; pref = (pref + (long long) middle[cur][i] * i) % mod; // bottom[who+1][i] += pref * (h - i); bottom[cur^1][i] = (bottom[cur^1][i] + (long long) pref * (h - i)) % mod; } pref = 0; for(int i = h - 1; i >= 0; --i) { // bottom[who+1][i] += pref * (i + 1); bottom[cur^1][i] = (bottom[cur^1][i] + (long long) pref * (i + 1)) % mod; // pref += middle[who][i] * (h - i); // actually, suffix pref = (pref + (long long) middle[cur][i] * (h - i)) % mod; } // middle -> middle pref = 0; for(int i = h - 1; i >= 0; --i) { // middle[who+1][i] += pref; add_self(middle[cur^1][i], pref); pref = (pref + (long long) middle[cur][i] * (h - i)) % mod; // pref += middle[who][i] * (h - i); // actually, suffix } // for(int i = 0; i < h; ++i) { // for(int j = i; j < h; ++j) { // bottom[who+1][j] += bottom[who][i] * (h - j); // } // middle[who+1][i] += bottom[who][i] * (h - i); // middle -> bottom // for(int j = 0; j < i; ++j) { // bottom[who+1][j] += middle[who][i] * (h - i) * (j + 1); // } // for(int j = i; j < h; ++j) { // bottom[who+1][j] += middle[who][i] * i * (h - j); // } // middle -> middle // for(int j = 0; j < i; ++j) { // middle[who+1][j] += middle[who][i] * (h - i) * 1; // } // } cur ^= 1; } long long answer = 0; for(int i = 0; i < h; ++i) { answer = (answer + (long long) bottom[cur][i] * (h - i) + (long long) middle[cur][i] * i % mod * (h - i)) % mod; // answer += (long long) bottom[w-1][i] * (h - i); // answer += (long long) middle[w-1][i] * i * (h - i); } printf("%lld\n", answer % mod); } |
English