public class BearDestroys {
int mod;
class Pair {
public int sum;
public int times;
public Pair(int sum, int times) {
this.sum = sum;
this.times = times;
}
public void modulo() {
sum %= mod;
times %= mod;
}
}
public int sumUp(int W, int H, int mod_) {
mod = mod_;
Pair cells[] = new Pair[H*W];
int iii = 0;
for(int s = 0; s <= W + H - 2; ++s)
for(int y = 0; y < H; ++y) {
int x = s - y;
if(0 <= x && x < W)
cells[iii++] = new Pair(x, y);
}
assert(iii == H * W);
final int M = 1 << (H + 1);
Pair dp[] = new Pair[M];
for(int i = 0; i < M; ++i) dp[i] = new Pair(0,0);
dp[0] = new Pair(0, 1);
for(iii = 0; iii < H * W; ++iii) {
int x = cells[iii].sum, y = cells[iii].times;
int bitRight = -1, bitDown = -1;
for(int j = 1; j <= H + 3 && iii + j < H * W; ++j) {
int xx = cells[iii+j].sum;
int yy = cells[iii+j].times;
if(x + 1 == xx && y == yy) bitRight = j;
if(x == xx && y + 1 == yy) bitDown = j;
}
Pair old[] = new Pair[M];
for(int i = 0; i < M; ++i) {
old[i] = new Pair(dp[i].sum, dp[i].times);
dp[i] = new Pair(0, 0);
}
for(int mask = 0; mask < M; ++mask) {
Pair me = old[mask];
Boolean right
= (0 == (mask
& (1 << bitRight
)) && x
!= W
-1); Boolean down
= (0 == (mask
& (1 << bitDown
)) && y
!= H
-1); if(0 != (mask & 1) || (!right && !down)) {
int m = mask / 2;
dp[m].sum += 2 * me.sum % mod;
dp[m].times += 2 * me.times % mod;
dp[m].modulo();
continue;
}
for(int hack = 0; hack < 2; ++hack) {
int m;
if(right && (prefer || !down))
m = mask / 2 + (1 << (bitRight-1));
else
m = mask / 2 + (1 << (bitDown - 1));
dp[m].sum += (me.sum + me.times) % mod;
dp[m].times += me.times;
dp[m].modulo();
prefer = true;
}
}
}
return dp[0].sum;
}
}