public class BearDestroysDiv2 {
int mod;
public class Pair {
public long sum;
public long times;
public Pair( long sum, long times) {
this .sum = sum;
this .times = times;
}
public void modulo( ) {
sum %= mod;
times %= mod;
}
}
public int sumUp( int W, int H, int mod_tmp) {
mod = mod_tmp;
final int M = 1 << ( W + 1 ) ;
Pair dp[ ] = new Pair[ M] ;
Pair old[ ] = new Pair[ M] ;
for ( int i = 0 ; i < M; ++ i) dp[ i] = new Pair( 0L,0L) ;
dp[ 0 ] = new Pair( 0L, 1L) ;
int x = 0 , y = 0 ;
while ( true ) {
for ( int mask = 0 ; mask < M; ++ mask) {
old[ mask] = new Pair( dp[ mask] .sum , dp[ mask] .times ) ;
dp[ mask] = new Pair( 0L, 0L) ;
}
for ( int mask = 0 ; mask < M; ++ mask) {
Pair me = old[ mask] ;
Boolean right
= ( 0 == ( mask
& 2 ) && x
!= W
- 1 ) ; Boolean down
= ( 0 == ( mask
& ( 1 << W
) ) && y
!= H
- 1 ) ; if ( 0 != ( mask & 1 ) || ( ! right && ! down) ) {
int m = mask / 2 ;
dp[ m] .sum += 2 * me.sum ;
dp[ m] .times += 2 * me.times ;
dp[ m] .modulo ( ) ;
continue ;
}
for ( int hack = 0 ; hack < 2 ; ++ hack) {
int m;
if ( right && ( prefer || ! down) )
m = mask / 2 + 1 ;
else
m = mask / 2 + ( 1 << ( W - 1 ) ) ;
dp[ m] .sum += me.sum + me.times ;
dp[ m] .times += me.times ;
dp[ m] .modulo ( ) ;
prefer = true ;
}
}
++ x;
if ( x == W) {
x = 0 ;
++ y;
}
if ( y == H) return ( int ) dp[ 0 ] .sum ;
}
}
}
cHVibGljIGNsYXNzIEJlYXJEZXN0cm95c0RpdjIgewogICAgCiAgICBpbnQgbW9kOwogICAgCiAgICBwdWJsaWMgY2xhc3MgUGFpciB7CiAgICAgICAgcHVibGljIGxvbmcgc3VtOwogICAgICAgIHB1YmxpYyBsb25nIHRpbWVzOwogICAgICAgIHB1YmxpYyBQYWlyKGxvbmcgc3VtLCBsb25nIHRpbWVzKSB7CiAgICAgICAgICAgIHRoaXMuc3VtID0gc3VtOwogICAgICAgICAgICB0aGlzLnRpbWVzID0gdGltZXM7CiAgICAgICAgfQogICAgICAgIHB1YmxpYyB2b2lkIG1vZHVsbygpIHsKICAgICAgICAgICAgc3VtICU9IG1vZDsKICAgICAgICAgICAgdGltZXMgJT0gbW9kOwogICAgICAgIH0KICAgIH0KICAgIAogICAgcHVibGljIGludCBzdW1VcChpbnQgVywgaW50IEgsIGludCBtb2RfdG1wKSB7CgkJbW9kID0gbW9kX3RtcDsKICAgICAgICBmaW5hbCBpbnQgTSA9IDEgPDwgKFcgKyAxKTsKICAgICAgICBQYWlyIGRwW10gPSBuZXcgUGFpcltNXTsKICAgICAgICBQYWlyIG9sZFtdID0gbmV3IFBhaXJbTV07CiAgICAgICAgZm9yKGludCBpID0gMDsgaSA8IE07ICsraSkgZHBbaV0gPSBuZXcgUGFpcigwTCwwTCk7CiAgICAgICAgZHBbMF0gPSBuZXcgUGFpcigwTCwgMUwpOwogICAgICAgIGludCB4ID0gMCwgeSA9IDA7CiAgICAgICAgd2hpbGUodHJ1ZSkgewogICAgICAgICAgICBmb3IoaW50IG1hc2sgPSAwOyBtYXNrIDwgTTsgKyttYXNrKSB7CiAgICAgICAgICAgICAgICBvbGRbbWFza10gPSBuZXcgUGFpcihkcFttYXNrXS5zdW0sIGRwW21hc2tdLnRpbWVzKTsKICAgICAgICAgICAgICAgIGRwW21hc2tdID0gbmV3IFBhaXIoMEwsIDBMKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IoaW50IG1hc2sgPSAwOyBtYXNrIDwgTTsgKyttYXNrKSB7CiAgICAgICAgICAgICAgICBQYWlyIG1lID0gb2xkW21hc2tdOwogICAgICAgICAgICAgICAgQm9vbGVhbiByaWdodCA9ICgwID09IChtYXNrICYgMikgJiYgeCAhPSBXLTEpOwogICAgICAgICAgICAgICAgQm9vbGVhbiBkb3duID0gKDAgPT0gKG1hc2sgJiAoMSA8PCBXKSkgJiYgeSAhPSBILTEpOwogICAgICAgICAgICAgICAgaWYoMCAhPSAobWFzayAmIDEpIHx8ICghcmlnaHQgJiYgIWRvd24pKSB7CiAgICAgICAgICAgICAgICAgICAgaW50IG0gPSBtYXNrIC8gMjsKICAgICAgICAgICAgICAgICAgICBkcFttXS5zdW0gKz0gMiAqIG1lLnN1bTsKICAgICAgICAgICAgICAgICAgICBkcFttXS50aW1lcyArPSAyICogbWUudGltZXM7CiAgICAgICAgICAgICAgICAgICAgZHBbbV0ubW9kdWxvKCk7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBCb29sZWFuIHByZWZlciA9IGZhbHNlOwogICAgICAgICAgICAgICAgZm9yKGludCBoYWNrID0gMDsgaGFjayA8IDI7ICsraGFjaykgewogICAgICAgICAgICAgICAgICAgIGludCBtOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGlmKHJpZ2h0ICYmIChwcmVmZXIgfHwgIWRvd24pKQogICAgICAgICAgICAgICAgICAgICAgICBtID0gbWFzayAvIDIgKyAxOwogICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgbSA9IG1hc2sgLyAyICsgKDEgPDwgKFcgLSAxKSk7CiAgICAgICAgICAgICAgICAgICAgZHBbbV0uc3VtICs9IG1lLnN1bSArIG1lLnRpbWVzOwogICAgICAgICAgICAgICAgICAgIGRwW21dLnRpbWVzICs9IG1lLnRpbWVzOwogICAgICAgICAgICAgICAgICAgIGRwW21dLm1vZHVsbygpOwogICAgICAgICAgICAgICAgICAgIHByZWZlciA9IHRydWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgKyt4OwogICAgICAgICAgICBpZih4ID09IFcpIHsKICAgICAgICAgICAgICAgIHggPSAwOwogICAgICAgICAgICAgICAgKyt5OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmKHkgPT0gSCkgcmV0dXJuIChpbnQpIGRwWzBdLnN1bTsKICAgICAgICB9CiAgICB9Cn0K