import java.util.*;
import java.io.*;
public class Main {
//所谓状态压缩,就是把复杂状态抽象为0和1来表示
//以列为单位进行状态转移,f[i][j]表示前i-1列已经放置完毕,第i列的状态,j用十进制整数来当作二进制使用,每个放个只有两个状态,放了放个或者没有放方格
//例如在2行4列的方格中,f[2][0]表示第2列的状态是0000,0表示这一格并没有放东西,每行j有2个状态所有最多有2^2的j,取决于行数
public static int N = 12,M = 1<<N,n,m;
static int[] st = new int[M];
static long[][] f = new long[N][M];
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(true){
String[] s = br.readLine().split(" ");
n = Integer.valueOf(s[0]);
m = Integer.valueOf(s[1]);
if(n==0&&m==0) break;
for(int i=0;i<(1<<n);i++){//当前循环判断0-2^n也就是压缩后所有状态是否可以存放竖条,竖条只能是连续偶数
int cnt = 0;
st[i] = 0;
for(int j=0;j<n;j++){
if((i>>j&1)==1){//用来计算10进制转化为2进制后每一位的数字
if((cnt&1)==1){//等价于cnt%2!=0,奇数&1为1,偶数&1为0
st[i]=1;
}
cnt=0;//每次判断完一次连续的偶数就要让cnt归零
}
else cnt++;
}
if((cnt&1)==1) st[i] = 1;//最后还要判断一次,例如1000,cnt是3但是不会进入上层循环的if中
}
for(int i=0;i<N;i++){//初始化f[][]
for(int j=0;j<M;j++){
f[i][j] = 0;
}
}
f[0][0]=1;//由于从0开始,f[0][0]自带初始一种方案
for(int i=1;i<=m;i++){
for(int j=0;j<(1<<n);j++){
for(int k=0;k<(1<<n);k++){
if((k&j)==0&&st[j|k]==0){
f[i][j] += f[i-1][k];
}
}
}
}
System.out.println(f[m][0]);//f[m][0]表示前m-1列已经排放完毕,且第m列没有放置
}
}
}
对于j|k的理解是,j是第i列我们想要放的状态,k是第i-1列我们已经放好的状态,我们这个j能不能摆放成功,需要判断一下我们摆完后k是不是合法的,我们已经知道1的话就是第i列会突出来的行数,即第i-1列这一行也被动的变成了1,所以用|运算来看摆放之后,第i-1列到底有多少个1,例如k=1001,j=0110,j|k=1111说明第i-1列已经放满了,这是合法的,这个j摆放是成功的,算一次,否则就不算。