Problem:
G: Computer Onesan / コンピュータおねえさん
ある日，おねえさんは，子供たちに組合せの数え方について教えてあげることになりました．
そこで，おねえさんは，次のような問題を解いてみることにしました．
縦幅 1 ，横幅 1 の正方形を縦幅
N
，横幅
M
の長方形に敷き詰めたときに，長方形の左上の頂点から右下の頂点への通り方が何通りあるかを数える
敷き詰めた正方形の辺の上しか通れない
それぞれの通り方は，同じ場所を1度しか通らない
図1に，
N
= 2,
M
= 2 の場合の全ての通り方を示します． 図1では，全部で12通りの通り方を示しており，その経路は赤い太線で表しています．
図1:
N
= 2,
M
= 2 の場合の全ての通り方
この問題では，
N
と
M
が少し大きくなるだけで，組合せの数が爆発的に増加してしまい，手で数えるのがとても難しくなってしまいます． そこで，おねえさんは，自分の頭脳をロボットに移植し，25万年をかけて，10 x 10 の場合の組合せの数を数える計画を立てました．
「10 x 10 なんて計算するとおねえさん死んじゃう！やめて！」
止める子供たちをよそに，おねえさんは，計算を開始します． おねえさんは，そこまでしてでも，子供たちに組合せ爆発のすごさを教えてあげたいのです．
おねえさんの熱意に心打たれたプログラマーのあなたは，この問題を解くプログラムを書いてあげることにしました． といっても，いきなり 10 x 10 を計算するプログラムを作るのは難しいので，手始めに
M
が小さい場合のプログラムを書くことにしました．
Input
入力は，1行に，
N
と
M
が半角スペースで与えられます．
N
は長方形の縦の幅で，1 <=
N
<= 100を満たします．
M
は長方形の横の幅で，1 <=
M
<= 2を満たします．
Output
入力に対する通り方の数を1行に出力してください． ただし，答えが非常に大きくなる場合があるので，1,000,000で割った余りを出力してください．
Sample Input 1
1 1
Sample Output 1
2
Sample Input 2
1 2
Sample Output 2
4
Sample Input 3
2 1
Sample Output 3
4
Sample Input 4
2 2
Sample Output 4
12
Sample Input 5
3 2
Sample Output 5
38

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define int long long

int n,m;
int dp1[111][111][3];
int dp2[111][111][111][3];

int dfs1(int A,int B,int d){
  if(n<A || n<B)return 0;
  if(B==n)return 1;
  if(dp1[A][B][d]!=-1)return dp1[A][B][d];
  
  int res=0;
  if(d==0){
    res += dfs1(A+1,B,0);
    if(A>B) res += dfs1(A,A,1);
  }
  if(d==1){
    res += dfs1(A,B+1,1);
    if(A<B) res += dfs1(B,B,0);
  }

  res %= 1000000;

  return dp1[A][B][d] = res;
  
}

int dfs2(int A,int B,int C,int d){
  if(n<A || n<B ||n<C)return 0;
  if(C==n)return 1;
  if(dp2[A][B][C][d]!=-1)return dp2[A][B][C][d];

  int res=0;
  if(d==0){
    if(A>B && A>C){
      int x = min(A-B,A-C)-1;
      res += dfs2(A,A,A,2) * x;
    }
    if(A>B){
      res += dfs2(A,A,C,1);
    }
    res += dfs2(A+1,B,C,0);
  }

  if(d==1){
    if(A<B) res += dfs2(B,B,C,0);
    res += dfs2(A,B+1,C,1);
    if(B>C) res += dfs2(A,B,B,2);
  }

  if(d==2){
    if(C>B && C>A){
      int x = min(C-B,C-A)-1;
      res += dfs2(C,C,C,0) * x;
    }
    if(C>B){
      res += dfs2(A,C,C,1);
    }
    res += dfs2(A,B,C+1,2);
  }

  res %= 1000000;

  return dp2[A][B][C][d] = res;
}

signed main(){
  cin>>n>>m;

  memset(dp1,-1,sizeof(dp1));
  memset(dp2,-1,sizeof(dp2));

  n++;

  if(m==1)cout<<dfs1(1,0,0)<<endl;
  else cout<<dfs2(1,0,0,0)<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 35452
final_rank: 3

code_snippet: #include <iostream>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef long long ll;
#define mod 1000000
int main() {
	int n, m;
	cin >> n >> m;
	ll rui[101];
	int r = 1;
	for (int i = 0; i < 101; i++)rui[i] = r, r = (r * 2) % mod;

	if (m == 2) {
		ll dp[101][101];
		memset(dp, 0, sizeof(dp));
		for (int j = 0; j <= n; j++)dp[0][j] += 1;
		for (int i = 1; i <= n; i++) {
			dp[i][i] += rui[i];
			for (int j = i + 1; j <= n; j++) {
				dp[i][j] += (rui[i - 1]);
			}
		}
		for (int i = 0; i <= n; i++) {
			for (int j = 0; j <= n; j++) {
				ll x = dp[i][j];
				if(i<n)dp[i + 1][j] += x;
				if (j < i) {
					for (int k = i + 1; k <= n; k++) {
						dp[k][k] = (dp[k][k] + (x*rui[k - i - 1] * (ll)(i - j + 1)) % mod) % mod;
						if (k == i + 1) {
							for (int l = k + 1; l <= n; l++) {
								dp[k][l] = (dp[k][l] + (x*(i - j))) % mod;
							}
						}
						else {
							for (int l = k + 1; l <= n; l++) {
								dp[k][l] = (dp[k][l] + (x*rui[k - i - 2] * (ll)(i - j + 1))) % mod;
							}
						}
					}
				}
			}
		}
		/*for (int i = 0; i <= n; i++) {
			for (int j = 0; j <= n; j++) {
				cout << dp[i][j] << " ";
			}
			cout << endl;
		}cout << endl;*/
		ll ans = 0;
		for (int j = 0; j <= n; j++) {
			ans += dp[n][j];
		}
		cout << ans % mod << endl; return 0;
	}
	else {
		cout << rui[n] << endl; return 0;
	}
	
}
accuracy: 1
time_ms: 10
memory_kb: 3164
final_rank: 1

code_snippet: #include<stdio.h>
#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>
#include <map>
#include <functional>
#include <stdio.h>
#include <array>
#include <algorithm>
#include <string>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<set>
#include<limits>
#include <complex>
using namespace std;

int N;
long long int memo[101][101][101][3];
long long int getans(vector<int>usenums,int now) {
	long long int *nmemo = &memo[usenums[0]][usenums[1]][usenums[2]][now];
	if (*nmemo >= 0) {
		return *nmemo;
	}
	else {
		if (now == 0) {
			if (usenums[0] == N) {
				return *nmemo = usenums[0] - max(usenums[1], usenums[2]) + 1;
			}
			else {
				long long int ans = 0;
				vector<int>nusenums(usenums);
				nusenums[0]++;
				ans += getans(nusenums, 0);
				nusenums[1] = nusenums[0];
				ans += getans(nusenums, 1);
				nusenums[2] = nusenums[0];
				ans+=(usenums[0] - max(usenums[1], usenums[2]) + 1)*getans(nusenums,2);
				ans %= 1000000;
				return *nmemo = ans;
			}
		}
		else if (now == 2) {
			if (usenums[2] == N) {
				return *nmemo = 1;
			}
			else {
				long long int ans = 0;
				vector<int>nusenums(usenums);
				nusenums[2]++;
				ans += getans(nusenums, 2);
				nusenums[1] = nusenums[2];
				ans += getans(nusenums, 1);
				nusenums[0] = nusenums[2];
				ans += (usenums[2] - max(usenums[1], usenums[0]) + 1)*getans(nusenums, 0);
				ans %= 1000000;
				return *nmemo = ans;
			}
		}
		else if(now==1){
			if (usenums[1] == N) {
				return *nmemo = 1;
			}
			else {
				long long int ans = 0;
				vector<int>nusenums(usenums);
				nusenums[1]++;
				ans += getans(nusenums, 1);
				nusenums[2] = nusenums[1];
				ans += getans(nusenums, 2);
				nusenums[2] = usenums[2];
				nusenums[0] = nusenums[1];
				ans +=getans(nusenums, 0);
				ans %= 1000000;
				return *nmemo = ans;
			}
		}
		else {
			assert(false);
		}
	}
}
int main() {
	memset(memo, -1, sizeof(memo));
	int  M; cin >> N >> M;
	long long int ans=0;
	if (M == 1) {
		ans = 1;
		while (N) {
			ans *= 2;
			ans %= 1000000;
			N--;
		}
		cout << ans << endl;
		return 0;
	}
	else {
		ans += getans(vector<int>({ 1, 0, 0 }), 0);
		ans += getans(vector<int>({ 1,1,0 }), 1);
		ans += getans(vector<int>({ 1,1,1, }), 2);
	}
	ans %= 1000000;
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 27320
final_rank: 5

code_snippet: #include<stdio.h>
#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>
#include <map>
#include <functional>
#include <stdio.h>
#include <array>
#include <algorithm>
#include <string>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<set>
#include<limits>
#include <complex>
using namespace std;

int N;
long long int memo[100][100][100][3];
long long int getans(vector<int>usenums,int now) {
	long long int *nmemo = &memo[usenums[0]][usenums[1]][usenums[2]][now];
	if (*nmemo >= 0) {
		return *nmemo;
	}
	else {
		if (now == 0) {
			if (usenums[0] == N) {
				return *nmemo = usenums[0] - max(usenums[1], usenums[2]) + 1;
			}
			else {
				long long int ans = 0;
				vector<int>nusenums(usenums);
				nusenums[0]++;
				ans += getans(nusenums, 0);
				nusenums[1] = nusenums[0];
				ans += getans(nusenums, 1);
				nusenums[2] = nusenums[0];
				ans+=(usenums[0] - max(usenums[1], usenums[2]) + 1)*getans(nusenums,2);
				ans %= 1000000;
				return *nmemo = ans;
			}
		}
		else if (now == 2) {
			if (usenums[2] == N) {
				return *nmemo = 1;
			}
			else {
				long long int ans = 0;
				vector<int>nusenums(usenums);
				nusenums[2]++;
				ans += getans(nusenums, 2);
				nusenums[1] = nusenums[2];
				ans += getans(nusenums, 1);
				nusenums[0] = nusenums[2];
				ans += (usenums[2] - max(usenums[1], usenums[0]) + 1)*getans(nusenums, 0);
				ans %= 1000000;
				return *nmemo = ans;
			}
		}
		else if(now==1){
			if (usenums[1] == N) {
				return *nmemo = 1;
			}
			else {
				long long int ans = 0;
				vector<int>nusenums(usenums);
				nusenums[1]++;
				ans += getans(nusenums, 1);
				nusenums[2] = nusenums[1];
				ans += getans(nusenums, 2);
				nusenums[2] = usenums[2];
				nusenums[0] = nusenums[1];
				ans +=getans(nusenums, 0);
				ans %= 1000000;
				return *nmemo = ans;
			}
		}
		else {
			assert(false);
		}
	}
}
int main() {
	memset(memo, -1, sizeof(memo));
	int  M; cin >> N >> M;
	long long int ans=0;
	if (M == 1) {
		ans = 1;
		while (N) {
			ans *= 2;
			ans %= 1000000;
			N--;
		}
		cout << ans << endl;
		return 0;
	}
	else {
		ans += getans(vector<int>({ 1, 0, 0 }), 0);
		ans += getans(vector<int>({ 1,1,0 }), 1);
		ans += getans(vector<int>({ 1,1,1, }), 2);
	}
	ans %= 1000000;
	cout << ans << endl;
	return 0;
}
accuracy: 0.6486486486486487
time_ms: 20
memory_kb: 26584
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#define M 1000000
using namespace std;

typedef long long ll;
int n,m,V;
map<ll, int> dp;

int rec(ll ma){
  if(dp.find(ma)!=dp.end())return dp[ma];
  
  int mate[4];
  ll k=1;
  for(int i=0;i<4;i++){
    mate[i] = (int)(ma%(1000*k)/k);
    k *= 1000;
  }

  int e = mate[0];
  if(e==5*n+2){
    if((!mate[1] || mate[1] == V-2) && (!mate[2] || mate[2] == V-1)
       && mate[3] == 1){
      return dp[ma] = 1;
    }else return dp[ma] = 0;
  }

  int ed = e%5;
  if(ed < 2){
    int a = (e/5)*3 + 1 + ed;
    int tmp[4]; for(int i=0;i<4;i++)tmp[i] = mate[i];
    tmp[0]++;
    ll t = 0; k = 1;

    for(int i=0;i<4;i++){
      t += tmp[i]*k; k*=1000;
    }
    int res = rec(t);

    if(!mate[ed+1] || !mate[ed+2])return dp[ma] = res;
    for(int i=1;i<4;i++){
      if(1<mate[i] && mate[i] < a-ed)return dp[ma] = 0;
    }

    if(ed == 0 && a!=1 && mate[1] == a 
       && mate[2] == a+1 && mate[3] == a+2)return dp[ma] = res;
    if(ed == 1 && a!=2 && mate[1] == a-1
       && mate[2] == a && mate[3] == a+1)return dp[ma] = res;
    if(ed == 0 && mate[1] == a+1 && mate[2] == a)return dp[ma] = res;
    if(ed == 1 && mate[2] == a+1 && mate[3] == a)return dp[ma] = res;

    if(mate[ed+1] == a)tmp[ed+1] = mate[ed+2];
    else{
      tmp[ed+1] = 0;
      for(int i=1;i<4;i++)if(tmp[i] == a)tmp[i] = mate[ed+2];
    }
    if(mate[ed+2] == a+1)tmp[ed+2] = mate[ed+1];
    else{
      tmp[ed+2] = 0;
      for(int i=1;i<4;i++)if(tmp[i] == a+1)tmp[i] = mate[ed+1];
    }

    t = 0; k = 1;
    for(int i=0;i<4;i++){
      t += tmp[i]*k; k*=1000;
    }
 
    res += rec(t);
    return dp[ma] = res % M;
  }else{
    ed -= 2;
    int a = (e/5)*3 + 1 + ed;
    
    int tmp[4]; for(int i=0;i<4;i++)tmp[i] = mate[i];
    tmp[0]++; tmp[ed+1] = a+3;
    ll t = 0; k = 1;
    for(int i=0;i<4;i++){
      t += tmp[i]*k; k*=1000;
    }
 
    int res = rec(t);
    
    if(!mate[ed+1])return dp[ma] = res;
    if(a!=1 && mate[ed+1] == a)return dp[ma] = res;
    if(a==1 && mate[ed+1] != a)return dp[ma] = res;
    
    for(int i=1;i<4;i++)if(tmp[i] == a)tmp[i] = a+3;
    tmp[ed+1] = mate[ed+1];
    t = 0; k = 1;
    for(int i=0;i<4;i++){
      t += tmp[i]*k; k*=1000;
    }
 
    res = rec(t);
    return dp[ma] = res;
  }
}

int main(){
  cin >> n >> m;

  if(m==1){
    int res = 1;
    while(n--){
      res <<= 1; res %= M;
    }
    cout << res << endl;
  }else{
    V = (n+1)*(m+1);
    ll v = 0, k = 1;
    for(int i=0;i<4;i++){
      v += i*k; k*=1000;
    }

    cout << rec(v) << endl;
    /*
      for(map<vector<int>,int>::iterator it=dp.begin();it!=dp.end();it++){
      for(int i=0;i<4;i++)cout << (*it).first[i] << " ";
      cout << (*it).second << endl;
      }
    */
  }
}
accuracy: 1
time_ms: 100
memory_kb: 17324
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#define M 1000000
using namespace std;

int n,m,V;
map<vector<char>, int> dp;

int rec(vector<char> mate){
  if(dp.find(mate)!=dp.end())return dp[mate];

  int e = (int)mate[0];
  if(e==5*n+2){
    if((!mate[1] || mate[1] == V-2) && (!mate[2] || mate[2] == V-1)
       && mate[3] == 1){
      return dp[mate] = 1;
    }else return dp[mate] = 0;
  }

  int ed = e%5;
  if(ed < 2){
    char a = (char)((e/5)*3 + 1 + ed);
    vector<char> tmp = mate;
    tmp[0]++;
    int res = rec(tmp);

    if(!mate[ed+1] || !mate[ed+2])return dp[mate] = res;
    if(ed == 0 && a!=1 && mate[1] == a 
       && mate[2] == a+1 && mate[3] == a+2)return dp[mate] = res;
    if(ed == 1 && a!=2 && mate[1] == a-1
       && mate[2] == a && mate[3] == a+1)return dp[mate] = res;
    if(ed == 0 && mate[1] == a+1 && mate[2] == a)return dp[mate] = res;
    if(ed == 1 && mate[2] == a+1 && mate[3] == a)return dp[mate] = res;

    if(mate[ed+1] == a)tmp[ed+1] = mate[ed+2];
    else{
      tmp[ed+1] = 0;
      for(int i=1;i<4;i++)if(tmp[i] == a)tmp[i] = mate[ed+2];
    }
    if(mate[ed+2] == a+1)tmp[ed+2] = mate[ed+1];
    else{
      tmp[ed+2] = 0;
      for(int i=1;i<4;i++)if(tmp[i] == a+1)tmp[i] = mate[ed+1];
    }

    res += rec(tmp);
    return dp[mate] = res % M;
  }else{
    ed -= 2;
    char a = (char)((e/5)*3 + 1 + ed);

    vector<char> tmp = mate;
    tmp[0]++; tmp[ed+1] = a+3;
    int res = rec(tmp);

    if(!mate[ed+1])return dp[mate] = res;
    if(a!=1 && mate[ed+1] == a)return dp[mate] = res;
    if(a==1 && mate[ed+1] != a)return dp[mate] = res;

    for(int i=1;i<4;i++)if(tmp[i] == a)tmp[i] = a+3;
    tmp[ed+1] = mate[ed+1];
    res = rec(tmp);
    return dp[mate] = res;
  }
}

int main(){
  cin >> n >> m;

  if(m==1){
    int res = 1;
    while(n--){
      res <<= 1; res %= M;
    }
    cout << res << endl;
  }else{
    V = (n+1)*(m+1);
    vector<char> v(4);
    for(int i=0;i<4;i++)v[i] = i;
    cout << rec(v) << endl;
    /*
    for(map<vector<int>,int>::iterator it=dp.begin();it!=dp.end();it++){
    for(int i=0;i<4;i++)cout << (*it).first[i] << " ";
    cout << (*it).second << endl;
    }
    */
  }
}
accuracy: 0.6486486486486487
time_ms: 20
memory_kb: 10128
final_rank: 6

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#define M 1000000
using namespace std;

int n,m,V;
map<vector<char>, int> dp;

int rec(vector<char> mate){
  if(dp.find(mate)!=dp.end())return dp[mate];

  char e = mate[0];
  if(e==5*n+2){
    if((!mate[1] || mate[1] == V-2) && (!mate[2] || mate[2] == V-1)
       && mate[3] == 1){
      return dp[mate] = 1;
    }else return dp[mate] = 0;
  }

  char ed = e%5;
  if(ed < 2){
    char a = (e/5)*3 + 1 + ed;
    vector<char> tmp = mate;
    tmp[0]++;
    int res = rec(tmp);

    if(!mate[ed+1] || !mate[ed+2])return dp[mate] = res;
    if(ed == 0 && a!=1 && mate[1] == a 
       && mate[2] == a+1 && mate[3] == a+2)return dp[mate] = res;
    if(ed == 1 && a!=2 && mate[1] == a-1
       && mate[2] == a && mate[3] == a+1)return dp[mate] = res;
    if(ed == 0 && mate[1] == a+1 && mate[2] == a)return dp[mate] = res;
    if(ed == 1 && mate[2] == a+1 && mate[3] == a)return dp[mate] = res;

    if(mate[ed+1] == a)tmp[ed+1] = mate[ed+2];
    else{
      tmp[ed+1] = 0;
      for(int i=1;i<4;i++)if(tmp[i] == a)tmp[i] = mate[ed+2];
    }
    if(mate[ed+2] == a+1)tmp[ed+2] = mate[ed+1];
    else{
      tmp[ed+2] = 0;
      for(int i=1;i<4;i++)if(tmp[i] == a+1)tmp[i] = mate[ed+1];
    }

    res += rec(tmp);
    return dp[mate] = res % M;
  }else{
    ed -= 2;
    char a = (e/5)*3 + 1 + ed;

    vector<char> tmp = mate;
    tmp[0]++; tmp[ed+1] = a+3;
    int res = rec(tmp);

    if(!mate[ed+1])return dp[mate] = res;
    if(a!=1 && mate[ed+1] == a)return dp[mate] = res;
    if(a==1 && mate[ed+1] != a)return dp[mate] = res;

    for(int i=1;i<4;i++)if(tmp[i] == a)tmp[i] = a+3;
    tmp[ed+1] = mate[ed+1];
    res = rec(tmp);
    return dp[mate] = res;
  }
}

int main(){
  cin >> n >> m;

  if(m==1){
    int res = 1;
    while(n--){
      res <<= 1; res %= M;
    }
    cout << res << endl;
  }else{
    V = (n+1)*(m+1);
    vector<char> v(4);
    for(int i=0;i<4;i++)v[i] = i;
    cout << rec(v) << endl;
    /*
    for(map<vector<int>,int>::iterator it=dp.begin();it!=dp.end();it++){
    for(int i=0;i<4;i++)cout << (*it).first[i] << " ";
    cout << (*it).second << endl;
    }
    */
  }
}
accuracy: 0.6486486486486487
time_ms: 20
memory_kb: 10132
final_rank: 7

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <cfloat>
#include <ctime>
#include <cassert>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <list>
#include <iomanip>
#include <fstream>
#include <bitset>
   
using namespace std;
   
 
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define foreach(it, c) for (__typeof__((c).begin()) it=(c).begin(); it != (c).end(); ++it)
#define rforeach(it, c) for (__typeof__((c).rbegin()) it=(c).rbegin(); it != (c).rend(); ++it)
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define CL(arr, val) memset(arr, val, sizeof(arr))
#define COPY(dest, src) memcpy(dest, src, sizeof(dest))
#define ten(n) ((long long)(1e##n))
#define bin(n) (1ull << (n))
#define erep(i, n) for (int i = 0; i <= (int)(n); ++i)
#define revrep(i, n) for (int i = (n); i >= 0; --i)
#define pb push_back

template <class T> void chmax(T& a, const T& b) { a = max(a, b); }
template <class T> void chmin(T& a, const T& b) { a = min(a, b); }

template <class T> void uniq(T& c) { sort(c.begin(), c.end()); c.erase(unique(c.begin(), c.end()), c.end()); }
 
template <class T> string to_s(const T& a) { ostringstream os; os << a; return os.str(); }
template <class T> T to_T(const string& s) { istringstream is(s); T res; is >> res; return res; }
  
template <class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p) { os << "( " << p.first << ", " << p.second << " )"; return os; }
  
template <class T> void print(T a, int n, const string& deli = " ", int br = 1) { for (int i = 0; i < n; ++i) { cout << a[i]; if (i + 1 != n) cout << deli; } while (br--) cout << endl; }
template <class T> void print(const T& c, const string& deli = " ", int br = 1) { foreach (it, c) { cout << *it; if (++it != c.end()) cout << deli;--it; } while (br--) cout << endl; }
template <class T> void print2d(T a, int w, int h, int width = -1, int br = 1) { for (int i = 0; i < h; ++i) { for (int j = 0; j < w; ++j) {    if (width != -1) cout.width(width); cout << a[i][j] << ' '; } cout << endl; } while (br--) cout << endl; }
   
template <class T> void input(T& a, int n) { for (int i = 0; i < n; ++i) cin >> a[i]; }
template <class T> void input(T* a, int n) { for (int i = 0; i < n; ++i) cin >> a[i]; }

void fix_pre(int n) { cout.setf(ios::fixed, ios::floatfield); cout.precision(10); }
void fast_io() { cin.tie(0); ios::sync_with_stdio(false); }
#define trace(x) (cout << #x << ": " << (x) << endl)
 
bool in_rect(int x, int y, int w, int h) { return 0 <= x && x < w && 0 <= y && y < h; }


typedef long long ll;
typedef pair<int, int> pint;
 
// y(v): v>^<  y(^): ^>v<
const int dx[] = { 0, 1, 0, -1 };
const int dy[] = { 1, 0, -1, 0 };

const double PI = acos(-1.0);



const int mod = ten(6);
void add(int& a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}
int main()
{
    int h, w;
    cin >> h >> w;

    if (w == 1)
    {
        int res = 1;
        rep(i, h)
            (res *= 2) %= mod;
        cout << res << endl;
        return 0;
    }

    static int dp[111][111][111][3]; // (last pos0~2, pos)
    dp[1][0][0][0] = 1;
    erep(i, h + 1) erep(j, h + 1) erep(k, h + 1) rep(pos, 3)
    {
        int cur = dp[i][j][k][pos];
        if (cur == 0)
            continue;

        if (pos == 0)
        {
            add(dp[i + 1][j][k][0], cur);
            
            if (i > j)
                add(dp[i][i][k][1], cur);

            int space = i - max(j, k) - 1;
            if (space > 0)
                add(dp[i][i][i][2], cur * space % mod);
        }
        else if (pos == 1)
        {
            if (j > i)
                add(dp[j][j][k][0], cur);

            add(dp[i][j + 1][k][1], cur);

            if (j > k)
                add(dp[i][j][j][2], cur);
        }
        else if (pos == 2)
        {
            int space = k - max(i, j) - 1;
            if (space > 0)
                add(dp[k][k][k][0], cur * space % mod);

            if (k > j)
                add(dp[i][k][k][1], cur);

            add(dp[i][j][k + 1][2], cur);
        }
    }

    int res = 0;
    erep(i, h + 1) erep(j, h + 1)
        add(res, dp[i][j][h + 1][2]);
    cout << res << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 15776
final_rank: 2