Problem:
Problem Statement
You have a rectangular board with square cells arranged in $H$ rows and $W$ columns.
The rows are numbered $1$ through $H$ from top to bottom, and the columns are numbered $1$ through $W$ from left to right. 
The cell at the row $i$ and the column $j$ is denoted by $(i, j)$. 
Each cell on the board is colored in either Black or White.
You will paint the board as follows:
Choose a cell $(i, j)$ and a color $c$, each uniformly at random, where $1 \le i \le H$, $1 \le j \le W$, and $c \in \{{\rm Black}, {\rm White}\}$.
Paint the cells $(i', j')$ with the color $c$ for any $1 \le i' \le i$ and $1 \le j' \le j$.
Here's an example of the painting operation.
You have a $3 \times 4$ board with the coloring depicted in the left side of the figure below.
If your random choice is the cell $(2, 3)$ and the color Black, the board will become as shown in the right side of the figure.
$6$ cells will be painted with Black as the result of this operation.
Note that we count the cells "painted" even if the color is not actually changed by the operation, like the cell $(1, 2)$ in this example.
Fig: An example of the painting operation
Given the initial coloring of the board and the desired coloring, you are supposed to perform the painting operations repeatedly until the board turns into the desired coloring.
Write a program to calculate the expected total number of painted cells in the sequence of operations.
Input
The input consists of several datasets. The number of datasets is at most $100$.
The first line of each dataset contains two integers $H$ and $W$ ($1 \le H, W \le 5$), the numbers of rows and columns of the board respectively.
Then given are two coloring configurations of the board, where the former is the initial coloring and the latter is the desired coloring.
A coloring configuration is described in $H$ lines, each of which consists of $W$ characters. Each character is either B or W, denoting a Black cell or a White cell, respectively.
There is one blank line between two configurations, and also after each dataset.
You can assume that the resulting expected value for each dataset will not exceed $10^9$.
The input is terminated by a line with two zeros, and your program should not process this as a dataset.
Output
For each dataset, your program should output the expected value in a line. The absolute error or the relative error in your answer must be less than $10^{-6}$.
Sample Input
1 2
BB

WW

2 1
B
W

B
W

2 2
BW
BW

WW
WW

3 4
BBBB
BBBB
BBBB

WWWW
WWWW
WWWW

5 5
BBBBB
BBBBB
BBBBB
BBBBB
BBBBB

BBBBB
BBBWB
BBBBB
BWBBB
BBBBB

0 0
Output for the Sample Input
6.0000000000
0.0000000000
12.8571428571
120.0000000000
23795493.8449918639

Submitted solutions:

code_snippet: #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const long double eps=1e-8;
struct state
{
	int a[7];
} ss[10000];
struct ones
{
	int a[6][6];
}Target,ini;
map<state,int> mm;
int n,m,TIME,num;
long double f[1000][1000],ans[1000];
bool operator < (const state &a,const state &b)
{
	for(int i=0;i<=m;i++) 
	{
		if(a.a[i]<b.a[i]) return 1;
		if(a.a[i]>b.a[i]) return 0;
	}
	return 0;
}
ones change_to_ones(state s)
{
	ones tmp=Target;
	int t=s.a[0];
	for(int j=1;j<=m;j++)
	{
		for(int i=1;i<=n-t;i++)
			tmp.a[i][j]=Target.a[i][j] ^ 1;
		t+=s.a[j];
	}
	return tmp;
}
state change_to_state(ones s)
{
	state tmp;
	int t=0;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	if(s.a[i][j]!=Target.a[i][j])
	{
		for(int ii=1;ii<=i;ii++)
		for(int jj=1;jj<=j;jj++)
			s.a[ii][jj]=Target.a[ii][jj] ^ 1;
	}
	tmp.a[0]=0;
	for(int i=n;i>=1;i--)
	{
		if(s.a[i][1]!=Target.a[i][1]) break;
		tmp.a[0]++;
	}
	for(int j=2;j<=m;j++)
	{
		tmp.a[j-1]=0;
		for(int i=n;i>=1;i--)
		{
			if(s.a[i][j]!=Target.a[i][j]) break;
			tmp.a[j-1]++;
		}
	}
	tmp.a[m]=n;
	for(int i=m;i>=1;i--)
		tmp.a[i]-=tmp.a[i-1];
	int yy;
	return tmp;
}
void dfs(state s,int dep,int rest)
{
	if(dep==m)
	{
		s.a[m]=rest;
		mm[s]=++TIME;
		ss[TIME]=s;
	}else
	{
		for(int i=0;i<=rest;i++)
		{
			s.a[dep]=i;
			dfs(s,dep+1,rest-i);
		}
	}
}
void build(int id)
{
	num++;
	for(int i=0;i<=TIME;i++) 
		f[num][i]=0;
	state now=ss[id];
	f[num][id]=1;
	if(now.a[0]==n) return;
	int TT=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		for(int col=0;col<=1;col++)
		{
			ones new_it=change_to_ones(now);
			for(int ii=1;ii<=i;ii++)
			for(int jj=1;jj<=j;jj++)
				new_it.a[ii][jj]=col;
			int tmp=mm[change_to_state(new_it)];
			f[num][tmp]-=(long double)1/(long double)(2 * n * m);
			f[num][0]+=(long double)(i*j)/(long double)(2 * n * m);
		}
}
void SWAP(int x,int y,int n)
{
	for(int i=0;i<=n;i++)
	{
		long double tmp=f[x][i];
		f[x][i]=f[y][i];
		f[y][i]=tmp;
	}
}
void add(int x,int y,int n)
{
	long double b=f[y][x]/f[x][x];
	for(int i=x;i<=n;i++)
		f[y][i]-=f[x][i] * b;
	f[y][0]-=f[x][0] * b;
}
void solve()
{
	int n=TIME;
	for(int i=1;i<=n;i++)
	{
		int flag=i;
		for(int j=i+1;j<=n;j++)
			if(fabs(f[j][i]>fabs(f[flag][i])))
				flag=j;
		SWAP(i,flag,n);
		for(int j=i+1;j<=n;j++)
			add(i,j,n);
	}
	for(int i=n;i>=1;i--)
	{
		for(int j=i+1;j<=n;j++)
			f[i][0]-=ans[j] * f[i][j];
		ans[i]=f[i][0]/f[i][i];
	}
}
int main()
{
	//freopen("i.out","w",stdout);
	//freopen("i.in","r",stdin);
	while (scanf("%d%d",&n,&m) && n!=0)
	{
		for(int i=1;i<=n;i++)
		{
			char ch[10];
			scanf("%s",ch+1);
			for(int j=1;j<=m;j++)
				ini.a[i][j]=(ch[j]=='B');
		}
		for(int i=1;i<=n;i++)
		{
			char ch[10];
			scanf("%s",ch+1);
			for(int j=1;j<=m;j++)
				Target.a[i][j]=(ch[j]=='B');
		}
		mm.clear();TIME=0;
		state s0;
		dfs(s0,0,n);
		num=0;
		for(int i=1;i<=TIME;i++)
			build(i);
		solve();
		printf("%.10f\n",(double)ans[mm[change_to_state(ini)]]);
	}
}
/*
3 3
BBB
BBB
BBB
WWW
WWW
WWW
*/
accuracy: 1
time_ms: 390
memory_kb: 6416
final_rank: 14

code_snippet: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

const int N = 10;
const int M = 505;

//0 ±íÊ¾ Ò»Ñù¡£
//1 ±íÊ¾²»Ò»Ñù¡£ 
//ÕÒµ½×îºóÒ»¸ö1µÄÎ»ÖÃ 

int n, m, hhash[8005], gxx = 0;
int num[M], area[M];
int msg[M];
char s[M][M], t[M][M];
double matrix[M][M];

struct St {
	int digit[N][N];
	void update() {
		int last = 0;
		for(int i = n; i >= 1; i--) {
			int ed = m;
			while(ed >= 1 && digit[i][ed] == 0) ed--;
			ed = max(ed, last);
			for(int j = 1; j <= ed; j++)
				digit[i][j] = 1;
			last = ed;
		}
	}
	int get_hash() {
		update();
		int res = 0;
		for(int i = 1; i <= n; i++) {
			int last = 1;
			while(digit[i][last] == 1 && last <= m) {
				last++;
			}
			last--;
			res *= 6;
			res += last;
		}
		return res;
	}
}start;

vector<St> seq;
double ans[M];

void solve() {
	for (int i = 1; i <= gxx; i++) {
		int k = i;
		for (int j = i + 1; j <= gxx; j++) {
			if (fabs(matrix[j][i]) > fabs(matrix[k][i])) {
				k = j;
			}
		}
		if (k != i) {
			for (int j = 1; j <= gxx + 1; j++) {
				swap(matrix[i][j], matrix[k][j]);
			}
		}
		for (int j = i + 1; j <= gxx; j++) {
			double x = matrix[j][i] / matrix[i][i];
			for (int k = i; k <= gxx + 1; k++) {
				matrix[j][k] -= matrix[i][k] * x;
			}
		}
	}
	ans[gxx] = matrix[gxx][gxx + 1] / matrix[gxx][gxx];
	for (int i = gxx - 1; i >= 1; i--) {
		for (int j = i + 1; j <= gxx; j++) {
			matrix[i][gxx + 1] -= matrix[i][j] * ans[j];
		}
		ans[i] = matrix[i][gxx + 1] / matrix[i][i];
	}
	return ;
}

int hash_add(int t) {
	if(hhash[t] == 0) {
		gxx++;
		hhash[t] = gxx;
	}
	return hhash[t];
}

void out() {
	St current;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			current.digit[i][j] = 0;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= msg[i]; j++)
			current.digit[i][j] = 1;
	int t = current.get_hash();
	if(!hhash[t]) {
		seq.push_back(current);
	}
	hash_add(t);
	return ;
}

void dfs(int x, int last) {
	if(x == 0) {
		out();
		return ;
	}
	for(int i = m; i >= last; i--) {
		msg[x] = i;
		dfs(x - 1, i);
		msg[x] = 0;
	}
}

void work() {
	gxx = 0;
	seq.clear();
	for(int i = 1; i <= n; i++)
		scanf("%s", s[i] + 1);
	for(int i = 1; i <= n; i++)
		scanf("%s", t[i] + 1);
	dfs(n, 0);
	for(int i = 1; i <= gxx; i++)
		for(int j = 1; j <= gxx + 1; j++)	
			matrix[i][j] = 0.;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++) {
			start.digit[i][j] = (s[i][j] != t[i][j]);
		}
	int st = hash_add(start.get_hash());
	for(int index = 0; index < seq.size(); index++) {
		St cur = seq[index], nxt;
		double value = 0;
	
		for(int k = 1; k <= gxx; k++) {
			num[k] = area[k] = 0;
		}
		
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= m; j++) {
				nxt = cur;
				for(int k1 = 1; k1 <= i; k1++)
					for(int k2 = 1; k2 <= j; k2++) {
						nxt.digit[k1][k2] = (t[k1][k2] != 'B');
					}
				int key = hash_add(nxt.get_hash());
				num[key]++;
				area[key] += i * j;
				for(int k1 = 1; k1 <= i; k1++) 
					for(int k2 = 1; k2 <= j; k2++) {
						nxt.digit[k1][k2] = (t[k1][k2] != 'W');
					}
				key = hash_add(nxt.get_hash());
				num[key]++;
				area[key] += i * j;
			}
		
		int sum = n * m * 2;
		
		for(int k = 1; k <= gxx; k++) {
			matrix[index + 1][k] =  1. * num[k] / sum;
			value += 1. / sum * area[k];
		}
		matrix[index + 1][gxx + 1] = -value;
	}
	for(int i = 1; i <= gxx; i++) {
		matrix[i][i] += -1;
	}
	for(int i = 1; i <= gxx + 1; i++) {
		matrix[gxx][i] = 0;
	}
	matrix[gxx][gxx] = 1.;
	solve();
	printf("%10f\n", ans[st]);	
	for(int i = 0; i < seq.size(); i++)
		hhash[seq[i].get_hash()] = 0;
}

int main() {;
	while(scanf("%d%d", &n, &m) == 2 && n && m) {
		work();
	}
	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 4684
final_rank: 1

code_snippet: #include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int MAXN = 555;
const int MAXS = 101111;
const int MAXH = 555;
const int MAXL = 555;
const long double eps = 1e-15;

int n, m, cnt, c[MAXN], l[MAXS], graph[MAXN][MAXN];
char a[MAXN][MAXN], b[MAXN][MAXN];

namespace Gaussian_Elimination{
	long double a[MAXH][MAXL + 1], x[MAXL];
	void init(int nE, int nV) {
		std::fill(x + 1, x + nV + 1, 0);
		for (int i = 1; i <= nE; i++)
			for (int j = 1; j <= nV + 1; j++)
				a[i][j] = 0;
	}
	int main(int nE, int nV) { // 0:Normal 1:No solution 2:multi-solution
		for (int h = 1; h <= nV; h++) {
			for (int i = h + 1; i <= nE; i++) {
				if (fabs(a[h][h]) > fabs(a[i][h])) continue;
				for (int j = 1; j <= nV + 1; j++)
					std::swap(a[h][j], a[i][j]);
			}
			if (fabs(a[h][h]) < eps) continue;
			for (int i = h + 1; i <= nE; i++) {
				if (fabs(a[i][h]) < eps) continue;
				long double t = a[i][h] / a[h][h];
				for (int j = h; j <= nV + 1; j++)
					a[i][j] -= a[h][j] * t;
			}
		}
		
		for (int h = nV + 1; h <= nE; h++) {
			if (fabs(a[h][nV + 1]) < eps) continue;
			return 1;
		}
		
		for (int h = nV; h >= 1; h--) {
			x[h] = a[h][nV + 1];
			for (int i = h + 1; i <= nV; i++)
				x[h] -= x[i] * a[h][i];
			if (fabs(a[h][h]) < eps) {
				if (fabs(x[h]) < eps) return 2;
				else return 1;
			}
			x[h] /= a[h][h];
		}
		return 0;
	}
};

int toInt(char c) {
	if (c == 'W') return 0;
	else return 1;
}

int getLabel(int *c) {
	int ret = 0;
	for (int i = 1; i <= n; i++)
		ret = ret * 6 + c[i];
	return ret;
}

void dfs(int h, int last) {
	if (h == n + 1) {
		l[getLabel(c)] = ++cnt;
		return;
	}
	for (int i = 0; i <= last; i++) {
		c[h] = i;
		dfs(h + 1, i);
	}
}

void getEquation(int h, int last) {
	if (h == n + 1) {
		static int tmp[MAXN][MAXN], cur[MAXN][MAXN], next[MAXN], graph[MAXN][MAXN];
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++)
				cur[i][j] = toInt(b[i][j]) ^ (j <= c[i]);
		}
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				for (int col = 0; col < 2; col++) {
					for (int k = 1; k <= n; k++)
						for (int l = 1; l <= m; l++) {
							tmp[k][l] = cur[k][l];
							graph[k][l] = 0;
						}
					for (int k = 1; k <= i; k++)
						for (int l = 1; l <= j; l++) {
							tmp[k][l] = col;
						}
					for (int k = 1; k <= n; k++)
						for (int l = 1; l <= m; l++)
							if (tmp[k][l] != toInt(b[k][l])) {
								for (int p = 1; p <= k; p++)
									for (int q = 1; q <= l; q++)
										graph[p][q] = 1;
							}
					for (int k = 1; k <= n; k++) {
						next[k] = 0;
						for (int l = 1; l <= m; l++)
							if (graph[k][l]) next[k] = l;
					}
					Gaussian_Elimination::a[l[getLabel(c)]][l[getLabel(next)]] -= 1.0 / n / m / 2.0;
					Gaussian_Elimination::a[l[getLabel(c)]][cnt + 1] += (long double)i * j / n / m / 2.0;
				}
		return;
	}
	for (int i = 0; i <= last; i++) {
		c[h] = i;
		getEquation(h + 1, i);
	}
}

int main() {
	while (scanf("%d%d", &n, &m) == 2) {
		if (n == 0 && m == 0) break;
		for (int i = 1; i <= n; i++) scanf("%s", a[i] + 1);
		for (int i = 1; i <= n; i++) scanf("%s", b[i] + 1);
		cnt = 0;
		dfs(1, m);
		Gaussian_Elimination::init(cnt, cnt);
		getEquation(1, m);
		for (int i = 1; i <= cnt; i++)
			Gaussian_Elimination::a[i][i]++;
		static int now[MAXN];
		for (int i = 1; i <= n; i++) now[i] = 0;
		for (int i = 1; i <= cnt + 1; i++) {
			Gaussian_Elimination::a[l[getLabel(now)]][i] = 0;
		}
		Gaussian_Elimination::a[l[getLabel(now)]][l[getLabel(now)]] = 1;
		Gaussian_Elimination::main(cnt, cnt);
		for (int k = 1; k <= n; k++)
			for (int l = 1; l <= m; l++)
				graph[k][l] = 0;
		for (int k = 1; k <= n; k++)
			for (int l = 1; l <= m; l++)
				if (a[k][l] != b[k][l]) {
					for (int p = 1; p <= k; p++)
						for (int q = 1; q <= l; q++)
							graph[p][q] = 1;
				}
		for (int k = 1; k <= n; k++) {
			now[k] = 0;
			for (int l = 1; l <= m; l++)
				if (graph[k][l]) now[k] = l;
		}
		double answer = Gaussian_Elimination::x[l[getLabel(now)]];
		printf("%.10f\n", answer);
		//Gaussian_Elimination::print(cnt, cnt);
	}
	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 13028
final_rank: 16

code_snippet: // AOJ #2573 Overwriting Game
// 2025.3.19

#include <bits/stdc++.h>
using namespace std;

const int N = 10, M = 260;
const double EPS = 1e-8;

bool A[N][N], B[N][N], f[N][N], g[N][N];
int n, m, s, tot, mp[1000005];
char buf[N];
double mat[M][M];

vector<int> tmp;
vector<int> st[M];

int hashState(const vector<int>& v) {
    int h = 0;
    for (int x : v) h = h * (n + 1) + x;
    return h;
}

void dfs(int u) {
    if (u == m) {
        mp[hashState(tmp)] = ++tot;
        st[tot] = tmp;
        return;
    }
    int start = (u == 0 ? n : tmp.back());
    for (int i = start; i >= 0; i--) {
        tmp.push_back(i);
        dfs(u + 1);
        tmp.pop_back();
    }
}

double gauss(int nn) {
    for (int i = 1; i <= nn; i++) {
        int pivot = i;
        for (int j = i; j <= nn; j++) {
            if (fabs(mat[j][i]) > fabs(mat[pivot][i])) pivot = j;
        }
        if (pivot != i) swap(mat[pivot], mat[i]);
        for (int j = 1; j <= nn; j++) {
            if (j == i) continue;
            double ratio = mat[j][i] / mat[i][i];
            for (int k = i + 1; k <= nn + 1; k++) mat[j][k] -= ratio * mat[i][k];
        }
    }
    return -mat[s][nn + 1] / mat[s][s];
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    while (true) {
        tot = 0;
        tmp.clear();
        memset(f, 0, sizeof(f));
        memset(g, 0, sizeof(g));
        memset(mp, 0, sizeof(mp));
        memset(mat, 0, sizeof(mat));

        cin >> n >> m;
        if(n == 0) break;

        for (int i = 0; i < n; i++){
            cin >> buf;
            for (int j = 0; j < m; j++) A[i][j] = (buf[j] == 'B');
        }
        for (int i = 0; i < n; i++){
            cin >> buf;
            for (int j = 0; j < m; j++) B[i][j] = (buf[j] == 'B');
        }

        int base = 0, inv = 2 * n * m;
        dfs(0);

        for (int i = n - 1; i >= 0; i--)
            for (int j = m - 1; j >= 0; j--){
                base += (i + 1) * (j + 1);
                bool okRight = (j == m - 1) || f[i][j + 1];
                bool okDown  = (i == n - 1) || f[i + 1][j];
                f[i][j] = okRight && okDown && (A[i][j] == B[i][j]);
            }
        base *= 2;

        tmp.clear();
        for (int j = 0; j < m; j++){
            int i;
            for (i = n - 1; i >= 0 && f[i][j]; i--);
            tmp.push_back(i + 1);
        }
        s = mp[hashState(tmp)];

        for (int o = 1; o <= tot; o++){
            if (o == tot) {
                mat[o][o] = 1;
                continue;
            }
            tmp = st[o];
            mat[o][o] = -inv;
            mat[o][tot + 1] = base;
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++) f[i][j] = (i >= tmp[j]);
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++){
                    for (int k = 0; k < 2; k++){
                        memcpy(g, f, sizeof(f));
                        for (int x = i; x >= 0; x--)
                            for (int y = j; y >= 0; y--)
                                g[x][y] = ((y == m - 1) || g[x][y + 1]) &&
                                  ((x == n - 1) || g[x + 1][y]) &&
                                  (k == B[x][y]);
                        vector<int> tmp2;
                        for (int x = 0; x < m; x++){
                            int y;
                            for (y = n - 1; y >= 0 && g[y][x]; y--);
                            tmp2.push_back(y + 1);
                        }
                        mat[o][mp[hashState(tmp2)]]++;
                    }
                }
        }
        cout << fixed << setprecision(10) << gauss(tot)+EPS << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 7964
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

void gaussian_elimination(int N, vector<vector<long double> >& mat) {
	for (int i = 0; i < N; i++) {
		int opt = -1;
		for (int j = i; j < N; j++) {
			if (opt == -1 || abs(mat[opt][i]) < abs(mat[j][i])) {
				opt = j;
			}
		}
		swap(mat[i], mat[opt]);
		long double mul = 1.0L / mat[i][i];
		for (int j = 0; j <= N; j++) {
			mat[i][j] *= mul;
		}
		for (int j = 0; j < N; j++) {
			if (j != i) {
				long double submul = mat[j][i];
				for (int k = i; k <= N; k++) {
					mat[j][k] -= mat[i][k] * submul;
				}
			}
		}
	}
}

long double solve(int H, int W, vector<string> S, vector<string> T) {
	string seq = string(W, 'A') + string(H, 'B');
	vector<int> bitlist;
	do {
		int bit = 0, x = H, y = 0;
		for (int i = 0; i < H + W; i++) {
			if (seq[i] == 'B') {
				x -= 1;
			}
			else {
				for (int j = x; j < H; j++) {
					bit |= 1 << (j * W + y);
				}
				y += 1;
			}
		}
		bitlist.push_back(bit);
	} while (next_permutation(seq.begin(), seq.end()));
	auto fix = [&](int bit) -> int {
		for (int i = H - 1; i >= 0; i--) {
			for (int j = W - 1; j >= 0; j--) {
				if (((bit >> (i * W + j)) & 1) == 0) {
					if (i != 0) bit &= ~(1 << ((i - 1) * W + j));
					if (j != 0) bit &= ~(1 << (i * W + (j - 1)));
				}
			}
		}
		return bit;
	};
	auto get = [&](int bit) -> int {
		return find(bitlist.begin(), bitlist.end(), fix(bit)) - bitlist.begin();
	};
	int N = bitlist.size();
	const long double pbase = 1.0L / (H * W * 2);
	vector<vector<long double> > p(N, vector<long double>(N));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < H; j++) {
			for (int k = 0; k < W; k++) {
				int b1 = bitlist[i];
				int b2 = bitlist[i];
				for (int x = 0; x <= j; x++) {
					for (int y = 0; y <= k; y++) {
						int id = x * W + y;
						if (T[x][y] == 'W') {
							b1 |= 1 << id;
							b2 &= ~(1 << id);
						}
						else {
							b1 &= ~(1 << id);
							b2 |= 1 << id;
						}
					}
				}
				p[i][get(b1)] += pbase;
				p[i][get(b2)] += pbase;
			}
		}
	}
	vector<vector<long double> > mat(N - 1, vector<long double>(N));
	for (int i = 0; i < N - 1; i++) {
		for (int j = 0; j < N - 1; j++) {
			mat[i][j] = -p[i][j] + (i == j ? 1 : 0);
		}
		mat[i][N - 1] = 1.0L;
	}
	gaussian_elimination(N - 1, mat);
	int basebit = 0;
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			if (S[i][j] == T[i][j]) {
				basebit |= 1 << (i * W + j);
			}
		}
	}
	int basepos = get(basebit);
	long double ans = (basepos != N - 1 ? mat[basepos][N - 1] : 0.0) * ((H + 1) * (W + 1) / 4.0);
	return ans;
}

int main() {
	while (true) {
		int H, W;
		cin >> H >> W;
		if (H == 0 && W == 0) {
			break;
		}
		vector<string> S(H), T(H);
		for (int i = 0; i < H; i++) {
			cin >> S[i];
		}
		for (int i = 0; i < H; i++) {
			cin >> T[i];
		}
		long double ans = solve(H, W, S, T);
		cout.precision(15);
		cout << fixed << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 5400
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rng(i, l, n) for(int i = l; i < n; i++)
#define rep(i, n) rng(i, 0, n)
using vi = vector<int>;

template <class T>
bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}
constexpr ll INF = 1e18;
constexpr ll e = -INF;

using vll = vector<long long>;

template <class T>
void view(T e) {
	cerr << e;
}

template <class T>
void view(vector<vector<T>> vv);

template <class T>
void view(vector<T> v);

template <class T>
void view(vector<vector<T>> vv) {
	cerr << "{ ";
	for(const auto &e : vv) {
		view(e);
		cerr << ", ";
	}
	cerr << "\b\b }";
}

template <class T, class U>
void view(map<T, U> m) {
	cerr << "{\n";
	for(auto &t : m) {
		cerr << '\t';
		view(t.first);
		cerr << ": ";
		view(t.second);
		cerr << '\n';
	}
	cerr << "}";
}
void view(ll e) {
	if(-e > INF / 2)
		cerr << "-INF";
	else if(e > INF / 2)
		cerr << "INF";
	else
		cerr << e;
}
template <class T>
void view(vector<T> v) {
	if(v.empty()) {
		cerr << "{ }";
		return;
	}
	cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		cerr << ", ";
	}
	cerr << "\b\b }";
}

void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	view(H);
	cerr << ", ";
	debug_out(T...);
}

#ifdef LOC
#define debug(...)                                           \
	do {                                                     \
		cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                              \
		cerr << "\b\b]\n";                                   \
	} while(0)
#else
#define debug(...) void(0)
#endif

struct stmax {
	int n;
	vector<ll> dat;
	stmax(int n) : n(n), dat(n + n, e) {}
	int left(int par) { return par * 2; }
	int right(int par) { return left(par) + 1; }
	void update(int idx, ll value) {
		idx += n;
		dat[idx] = value;
		idx >>= 1;
		while(idx) {
			dat[idx] = max(dat[left(idx)], dat[right(idx)]);
			idx >>= 1;
		}
	}

	void kaizen(int idx, ll value) {
		ll old = get(idx, idx + 1);
		if(value > old) update(idx, value);
	}

	ll get(int l, int r = -1) {
		if(r < 0) r = l + 1;
		assert(0 <= l && l <= r && r <= n);
		l += n;
		r += n;
		ll ret = e;
		while(l < r) {
			if(l & 1) {
				chmax(ret, dat[l]);
				l++;
			}
			l >>= 1;
			if(r & 1) {
				chmax(ret, dat[r - 1]);
				r--;
			}
			r >>= 1;
		}
		return ret;
	}

	void print() {
#ifdef LOC
		cerr << '[' << ' ';
		rep(i, n) {
			view(get(i));
			cerr << ' ';
		}
		cerr << "]";
		cerr << '\n';
#endif
	}
};

constexpr int mod = 998244353;
struct mint {
	ll x;
	mint(ll y = 0) : x(y % mod) {
		if(x < 0) x += mod;
	}
	mint operator+(mint b) { return mint(x + b.x); }
	mint operator-(mint b) { return mint(x - b.x); }
	mint operator-() { return mint(-x); }
	mint operator*(mint b) { return mint(x * b.x); }
	mint &operator+=(mint b) { return *this = *this + b; }
	mint &operator-=(mint b) { return *this = *this - b; }
	mint &operator*=(mint b) { return *this = *this * b; }

	mint pow(ll n) {
		mint mult = x;
		mint ret = 1;
		while(n) {
			if(n & 1) ret *= mult;
			n >>= 1;
			mult *= mult;
		}
		return ret;
	}

	mint inv() {
		assert(x);
		return pow(mod - 2);
	}

	mint operator/(mint b) { return *this * b.inv(); }
	mint &operator/=(mint b) { return *this = *this / b; }
};

double solve(int h) {
	int w;
	cin >> w;
	vector<int> vec(h, 0);
	map<vector<int>, int> id;
	auto dfs = [&](auto self, int place, int val) -> void {
		if(place == h) {
			id[vec] = 0;
			return;
		}
		rng(nxtval, 0, val + 1) {
			vec[place] = nxtval;
			self(self, place + 1, nxtval);
		}
	};

	dfs(dfs, 0, w);

	int idmax = 0;
	vector<vi> states;
	for(auto &t : id) {
		t.second = idmax++;
		states.push_back(t.first);
	}
	debug(id);
	debug(states);

	vector<vector<int>> start(h, vi(w));
	auto goal = start;
	rep(i, h) rep(j, w) {
		char c;
		cin >> c;
		start[i][j] = c == 'W';
	}
	rep(i, h) rep(j, w) {
		char c;
		cin >> c;
		goal[i][j] = c == 'W';
	}

	auto f = [](vector<int> &v) {
		int len = int(v.size());
		for(int i = len - 1; i > 0; i--) {
			chmax(v[i - 1], v[i]);
		}
	};

	vector<vector<double>> mat(idmax, vector<double>(idmax + 1, 0));

	vector<int> initstate(h, 0);
	rep(row, h) {
		for(int col = w - 1; col > -1; col--) {
			if(start[row][col] != goal[row][col]) {
				initstate[row] = col + 1;
				break;
			}
		}
	}
	debug(start);
	debug(goal);
	f(initstate);
	debug(initstate);
	const int init_pos = id.at(initstate);
	const int goal_id = id.at(vector<int>(h, 0));
	const double prob = 1. / h / w / 2;
	rep(from_id, idmax) {
		if(from_id == goal_id) continue;
		vector<int> same_from = states[from_id];
		auto &matrow = mat[from_id];
		rng(xmax, 1, h + 1) rng(ymax, 1, w + 1) rep(paint, 2) {
			vector<int> same_to(h);
			rep(row, h) {
				int &tmp = same_to[row] = 0;
				for(int col = w - 1; col > -1; col--) {
					bool converted_same = (row < xmax && col < ymax) ? paint == goal[row][col] : col >= same_from[row];
					if(!converted_same) {
						tmp = col + 1;
						break;
					}
				}
			}
			debug(same_from, xmax, ymax, paint);
			debug(same_to);
			f(same_to);
			int id_to = id.at(same_to);
			matrow[id_to] += -prob;
		}
		matrow[from_id] += 1;
		matrow.back() += 1;
		debug(matrow);
	}
	mat[goal_id][goal_id] = 1;

	debug(init_pos, goal_id);
	debug(mat);

	const int height = mat.size();
	const int width = mat.front().size();
	rep(col, height) {
		int nxtrow = -1;
		double sz = -1;
		rng(row, col, idmax) {
			if(chmax(sz, abs(mat[row][col]))) {
				nxtrow = row;
			}
		}
		swap(mat[col], mat[nxtrow]);
		auto &sw = mat[col];
		const double value = sw[col];
#ifdef LOC
		assert(abs(value) > 1e-15);
#endif
		rng(j, col, width) { sw[j] /= value; }

		rng(row, 0, height) {
			if(row == col) continue;
			double mult = -mat[row][col];
			rng(j, col, width) { mat[row][j] += mult * sw[j]; }
		}

		debug(mat);
	}

	return mat.at(init_pos).back() * (h + 1) * (w + 1) / 2 / 2;
}

int main() {
	ll n;
	cout << fixed << setprecision(15);
	while(cin >> n && n) {
		cout << solve(n);
		cout << '\n';
	};
}
accuracy: 1
time_ms: 150
memory_kb: 3840
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=100005,INF=1<<30;

const double eps=1e-8;
typedef vector<double> vec;
typedef vector<vec> mat;

vec gauss_jordan(const mat& A,const vec &b){
    int n=A.size();
    mat B(n,vec(n+1));
    
    for(int i=0;i<n;i++) for(int j=0;j<n;j++) B[i][j]=A[i][j];
    
    for(int i=0;i<n;i++) B[i][n]=b[i];
    
    for(int i=0;i<n;i++){
        int pivot=i;
        for(int j=i;j<n;j++){
            if(abs(B[j][i])>abs(B[pivot][i])) pivot=j;
        }
        swap(B[i],B[pivot]);
        
        if(abs(B[i][i])<eps) return vec();
        
        for(int j=i+1;j<=n;j++) B[i][j]/=B[i][i];
        for(int j=0;j<n;j++){
            if(i!=j){
                for(int k=i+1;k<=n;k++) B[j][k]-=B[j][i]*B[i][k];
            }
        }
    }
    
    vec x(n);
    
    for(int i=0;i<n;i++) x[i]=B[i][n];
    return x;
}

vector<vector<int>> A;
map<vector<int>,int> MA;
vector<int> now;
int H,W;

void DFS(int h,int w){
    if(h==-1){
        MA[now]=si(A);
        A.push_back(now);
        return;
    }
    
    for(int j=w;j>=0;j--){
        now.push_back(j);
        DFS(h-1,j);
        now.pop_back();
    }
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        cin>>H>>W;
        if(H==0) break;
        vector<string> S(H),T(H);
        for(int i=0;i<H;i++) cin>>S[i];
        for(int i=0;i<H;i++) cin>>T[i];
        A.clear();MA.clear();
        DFS(H-1,W);
        
        int N=si(A);
        string V="BW";
        
        auto idx=[&](vector<string> U){
            vector<int> match;
            for(int i=H-1;i>=0;i--){
                int cn=0;
                for(int j=W-1;j>=0;j--){
                    if(T[i][j]==U[i][j]) cn++;
                    else break;
                }
                if(si(match)==0) match.push_back(cn);
                else{
                    chmin(cn,match.back());
                    match.push_back(cn);
                }
            }
            return MA[match];
        };
        
        mat X(N,vec(N));
        vec Y(N);
        
        for(int i=0;i<N;i++){
            if(i==0){
                X[i][i]=1.0;
                Y[i]=0.0;
                continue;
            }
            for(int a=1;a<=H;a++){
                for(int b=1;b<=W;b++){
                    for(char c:V){
                        vector<string> U(H,string(W,'#'));
                        for(int h=0;h<H;h++){
                            for(int w=0;w<A[i][h];w++) U[H-1-h][W-1-w]=T[H-1-h][W-1-w];
                        }
                        for(int h=0;h<a;h++){
                            for(int w=0;w<b;w++){
                                U[h][w]=c;
                            }
                        }
                        int z=idx(U);
                        X[i][z]+=1.0/(H*W*2);
                        Y[i]-=(double)a*b/(H*W*2);
                    }
                }
            }
            X[i][i]-=1.0;
        }
        
        auto Z=gauss_jordan(X,Y);
        
        cout<<fixed<<setprecision(25)<<(Z[idx(S)])<<"\n";
    }
}
accuracy: 1
time_ms: 220
memory_kb: 4344
final_rank: 6

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

typedef long double Data;
typedef vector<Data> Array;
typedef vector<Array> mat;

bool is_zero(Data dat) { return abs(dat) < eps; }
mat operator-(mat a) {
	rep(i, a.size())rep(j, a[0].size())a[i][j] = -a[i][j];
	return a;
}
mat operator+(mat lhs, mat& rhs) {
	rep(i, lhs.size())rep(j, lhs[0].size())lhs[i][j] += rhs[i][j];
	return lhs;
}
mat operator-(mat lhs, mat& rhs) {
	rep(i, lhs.size())rep(j, lhs[0].size())lhs[i][j] -= rhs[i][j];
	return lhs;
}
mat operator*(const mat& lhs, const mat& rhs) {
	mat ret(lhs.size(), Array(rhs[0].size(), 0));
	rep(i, lhs.size())rep(j, rhs[0].size())rep(k, rhs.size()) {
		ret[i][j] += lhs[i][k] * rhs[k][j];
	}
	return ret;
}
//no verify
int rankMat(mat a) {
	const int n = a.size(), m = a[0].size();
	int r = 0;
	for (int i = 0; r < n && i < m; ++i) {
		int pivot = r;
		for (int j = r + 1; j < n; ++j)
			if (abs(a[j][i]) > abs(a[pivot][i]))pivot = j;
		swap(a[pivot], a[r]);
		if (is_zero(a[r][i]))continue;
		for (int k = m - 1; k >= i; --k)
			a[r][k] = a[r][k] / a[r][i];
		for (int j = r + 1; j < n; ++j) {
			for (int k = m - 1; k >= i; --k) {
				a[j][k] = fma(-a[r][k], a[j][i], a[j][k]);
			}
		}
		++r;
	}
	return r;
}
mat scalar(int sz, Data k) {
	mat ret(sz, Array(sz, 0));
	rep(i, sz)ret[i][i] = k;
	return ret;
}
//行列累乗
mat operator^(const mat& lhs, const ll n) {
	if (n == 0)return scalar(lhs.size(), 1);
	mat ret = (lhs * lhs) ^ (n / 2);
	if (n % 2) {
		ret = ret * lhs;
	}
	return ret;
}

Data det(mat a) {
	const int n = a.size();
	Data D = Data(1);
	for (int i = 0; i < n; ++i) {
		int pivot = i;
		for (int j = i + 1; j < n; ++j) {
			if (abs(a[j][i]) > abs(a[pivot][i]))pivot = j;
		}
		swap(a[pivot], a[i]);
		D = D * a[i][i] * Data(i != pivot ? -1 : 1);
		if (is_zero(a[i][i]))break;
		for (int j = i + 1; j < n; ++j) {
			for (int k = n - 1; k >= i; --k) {
				a[j][k] = a[j][k] - a[i][k] * a[j][i] / a[i][i];
			}
		}
	}
	return D;
}

pair<mat, vector<int>> LUPDecomposition(mat a) {
	int n = a.size();
	vector<int> perm(n);
	iota(begin(perm), end(perm), 0);
	rep(i, n) {
		int pivot = i;
		for (int j = i + 1; j < n; ++j)
			if (abs(a[j][i]) > abs(a[pivot][i]))pivot = j;
		swap(a[pivot], a[i]);
		swap(perm[pivot], perm[i]);
		for (int j = i + 1; j < n; ++j) {
			a[j][i] /= a[i][i];
			for (int k = i + 1; k < n; ++k) {
				a[j][k] -= a[i][k] * a[j][i];
			}
		}
	}
	return make_pair(a, perm);
}
Array LUPBackSubstitution(mat& LU, vector<int>& perm, Array a) {
	int n = LU.size();
	Array tmp(n);
	rep(i, n)tmp[i] = a[perm[i]];
	swap(tmp, a);
	rep(i, n) {
		rep(j, i) {
			a[i] -= a[j] * LU[i][j];
		}
	}
	for (int i = n - 1; i >= 0; --i) {
		for (int j = i + 1; j < n; ++j) {
			a[i] -= a[j] * LU[i][j];
		}
		a[i] /= LU[i][i];
	}
	return a;
}

//Ax=bのxを返す
Array calc(mat A, Array b) {
	pair<mat, vector<int>> p = LUPDecomposition(A);
	return LUPBackSubstitution(p.first, p.second, b);
}
int h, w;

void solve() {
	vector<string> s(h), t(h);
	rep(i, h)cin >> s[i];
	rep(i, h)cin >> t[i];
	vector<vector<bool>> bt(h);
	rep(i, h) {
		bt[i].resize(w);
		rep(j, w) {
			if (t[i][j] == 'W')bt[i][j] = 1;
			else bt[i][j] = 0;
		}
	}
	auto trans = [&](int s) {
		vector<P> vp;
		rep(i, h) {
			int chk = -1;
			per(j, w) {
				bool b = s & (1 << (i * w + j));
				if (b != bt[i][j]) {
					chk = j; break;
				}
			}
			while (vp.size() && vp.back().second <=chk) {
				vp.pop_back();
			}
			if(chk>=0)vp.push_back({ i,chk });
		}
		int res = 0;
		for (P p : vp) {
			res |= 1 << (p.first * w + p.second);
		}
		return res;
	};
	int ori = 0;
	rep(i, h)rep(j, w)if (s[i][j] == 'W') {
		ori |= 1 << (i * w + j);
	}
	int cur = 0;
	rep(i, h)rep(j, w)if (t[i][j] == 'W') {
		cur |= 1 << (i * w + j);
	}
	vector<int> vs;
	function<void(int)> dfs = [&](int dep) {
		if (dep == h) {
			//cout << cur << " " << trans(cur) << "\n";
			vs.push_back(trans(cur));
			return;
		}
		dfs(dep+1);
		//int memcur = cur;
		rep(j, w) {
			cur ^= 1 << (dep * w + j);
			dfs(dep + 1);
			cur ^= 1 << (dep * w + j);
		}
	};
	dfs(0);
	sort(all(vs));
	vs.erase(unique(all(vs)), vs.end());
	mat A(vs.size(), Array(vs.size()));
	Array b(vs.size());
	b[0] = 0;
	A[0][0] = 1;

	vector<vector<int>> colw(h, vector<int>(w));
	vector<vector<int>> colb(h, vector<int>(w));
	rep(i, h)rep(j, w) {
		rep(k, i + 1)rep(l, j + 1) {
			colw[i][j] |= 1 << (k * w + l);
		}
		colb[i][j] = (1 << (h * w)) - 1 - colw[i][j];
	}
	ld coef = 1 / (ld)(h * w * 2);
	rep1(i, vs.size() - 1) {
		A[i][i] = 1;
		int nw = cur;
		rep(x, h)rep(y, w) {
			if (vs[i] & (1 << (x * w + y))) {
				nw ^= (1 << (x * w + y));
			}
		}
		rep(x, h)rep(y, w) {
			int to = nw | colw[x][y];
			to = trans(to);
			to = lower_bound(all(vs), to) - vs.begin();
			assert(0 <= to && to < vs.size());
			b[i] += (x + 1) * (y + 1) * coef;
			A[i][to] -= coef;

			to = nw & colb[x][y];
			to = trans(to);
			to = lower_bound(all(vs), to) - vs.begin();
			assert(0 <= to && to < vs.size());
			b[i] += (x + 1) * (y + 1) * coef;
			A[i][to] -= coef;
		}
	}
	Array x = calc(A, b);
	int ansloc = lower_bound(all(vs), trans(ori)) - vs.begin();
	//coutarray(x);
	cout << x[ansloc] << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	while(cin>>h>>w,h)
	solve();
	return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 15664
final_rank: 18

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;

#define EPS 0.00000000001

#define NUM 6
#define MAX 252

typedef vector<double> V;
typedef vector<V> MATRIX;

struct Info{
	Info(int arg_state,int arg_num_paint){
		state = arg_state;
		num_paint = arg_num_paint;
	}
	int state,num_paint;
};

int H,W;
int POW[26],state_index,ans_state;
int first_state;
map<int,int> STATE,PAINT;
char first[NUM][NUM],last[NUM][NUM],color[2] = {'B','W'};
double P_table[MAX][MAX],ADD_table[MAX][MAX];


int get_code(char table[NUM][NUM]){

	int ret = 0;
	int index = 0;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] == 'B'){
				ret += POW[index];
			}
			index++;
		}
	}
	return ret;
}

int get_state(char table[NUM][NUM]){

	int first_code = get_code(table); //最初の状態

	auto at1 = PAINT.find(first_code);
	auto at2 = STATE.find(PAINT[first_code]);

	if(at1 != PAINT.end() && at2 != STATE.end()){

		return STATE[PAINT[first_code]]; //既に状態が登録済ならreturn
	}


	char work[NUM][NUM];

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			work[row][col] = table[row][col];
		}
	}

	//★★正しい状態に遷移させるために、最小限塗らなければならない場所が同一ならば、同じ状態と見なす★★

	int index = H*W-1,paint_state = 0;

	for(int row = H-1; row >= 0; row--){
		for(int col = W-1; col >= 0; col--){
			if(work[row][col] != last[row][col]){ //左上方向に向かって塗らなければならない場所を探す

				paint_state += POW[index];
				for(int a = row; a >= 0; a--){
					for(int b = col; b >= 0; b--){
						work[a][b] = last[row][col];
					}
				}
			}
			index--;
		}
	}

	at2 = STATE.find(paint_state);

	if(at2 != STATE.end()){ //塗った状態は登録されている場合

		PAINT[first_code] = paint_state;
		return STATE[paint_state];
	}

	PAINT[first_code] = paint_state; //first_codeが塗らなければならない場所を登録
	return STATE[paint_state] = state_index++;
}

void calc_states(char first_table[NUM][NUM]){

	int first_code = get_code(first_table); //最初の状態

	queue<int> Q;
	Q.push(first_code);

	int base_code,base_state,tmp_code,tmp_state,index;
	char base_table[NUM][NUM],work[NUM][NUM];

	bool check[MAX];

	for(int i = 0; i < MAX; i++){

		check[i] = false;
	}

	while(!Q.empty()){

		base_code = Q.front();
		Q.pop();

		index = 0;

		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				if(base_code & (1 << index)){
					base_table[row][col] = 'B';
				}else{
					base_table[row][col] = 'W';
				}
				index++;
			}
		}

		base_state = get_state(base_table);
		check[base_state] = true;

		//次に遷移する状態を全探索する

		int count;

		//次の状態を全て試す(最大H*W*2通り)
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				for(int a = 0; a < 2; a++){

					for(int i = 0; i < H; i++){
						for(int k = 0; k < W; k++){
							work[i][k] = base_table[i][k];
						}
					}

					count = 0;

					for(int i = row; i >= 0; i--){
						for(int k = col; k >= 0; k--){
							count++;
							work[i][k] = color[a];
						}
					}


					tmp_state = get_state(work);

					P_table[base_state][tmp_state] += 1.0/(double)(2*H*W);
					ADD_table[base_state][tmp_state] += ((row+1)*(col+1))/(double)(2*H*W);

					if(!check[tmp_state]){

						check[tmp_state] = true;
						tmp_code = get_code(work);

						index = 0;

						for(int a = 0; a < row; a++){
							for(int b = 0; b < col; b++){
								if(tmp_code & (1 << index)){

									work[a][b] = 'B';

								}else{
									work[a][b] = 'W';
								}
							}
						}

						Q.push(tmp_code);
					}
				}
			}
		}
	}
}

MATRIX gauss_jordan(MATRIX A,int SIZE){

	MATRIX C(SIZE,V(SIZE+1));

	for(int row = 0; row < SIZE; row++){
		for(int col = 0; col <= SIZE; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	for(int i = 0; i < SIZE; i++){
		base_row = i;
		for(int row = i+1; row < SIZE; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue; //操作不要

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col <= SIZE; col++){ //基準行の係数を1にする
			C[i][col] /= tmp;
		}

		for(int row = 0; row < SIZE; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue; //基準行、または該当列が0ならSKIP

			tmp = C[row][i];

			for(int col = i; col <= SIZE; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
	}

	return C;
}

void func(){

	for(int row = 0; row < H; row++){
		scanf("%s",first[row]);
	}


	for(int row = 0; row < H; row++){

		scanf("%s",last[row]);
	}

	STATE.clear();
	PAINT.clear();

	state_index = 0;

	for(int i = 0; i < MAX; i++){
		for(int k = 0; k < MAX; k++){
			P_table[i][k] = 0;
			ADD_table[i][k] = 0;
		}
	}

	calc_states(first);

	first_state = get_state(first);
	ans_state = get_state(last);

	//return;
	MATRIX A(state_index,V(state_index+1));

	for(int row = 0; row < state_index; row++){
		for(int col = 0; col <= state_index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < state_index; i++){

		A[i][i] = 1.0;

		if(i == ans_state)continue;

		for(int k = 0; k < state_index; k++){

			A[i][k] -= P_table[i][k];
			A[i][state_index] += ADD_table[i][k]; //塗る枚数
		}
	}

	A = gauss_jordan(A,state_index);

	printf("%.10lf\n",A[first_state][state_index]);

	return;
}


int main(){

	POW[0] = 1;

	for(int i = 1; i < 26; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d %d",&H,&W);
		if(H == 0&& W == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 5532
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;

#define EPS 0.000000000001

#define NUM 6
#define MAX 252

typedef vector<double> V;
typedef vector<V> MATRIX;

struct Info{
	Info(int arg_state,int arg_num_paint){
		state = arg_state;
		num_paint = arg_num_paint;
	}
	int state,num_paint;
};

int H,W;
int POW[26],state_index,ans_state;
int first_state;
map<int,int> STATE,PAINT;
char first[NUM][NUM],last[NUM][NUM],color[2] = {'B','W'};
double P_table[MAX][MAX],ADD_table[MAX][MAX];


int get_code(char table[NUM][NUM]){

	int ret = 0;
	int index = 0;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] == 'B'){
				ret += POW[index];
			}
			index++;
		}
	}
	return ret;
}

int get_state(char table[NUM][NUM]){

	int first_code = get_code(table); //最初の状態

	auto at1 = PAINT.find(first_code);
	auto at2 = STATE.find(PAINT[first_code]);

	if(at1 != PAINT.end() && at2 != STATE.end()){

		return STATE[PAINT[first_code]]; //既に状態が登録済ならreturn
	}


	char work[NUM][NUM];

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			work[row][col] = table[row][col];
		}
	}

	//★★正しい状態に遷移させるために、最小限塗らなければならない場所が同一ならば、同じ状態と見なす★★

	int index = H*W-1,paint_state = 0;

	for(int row = H-1; row >= 0; row--){
		for(int col = W-1; col >= 0; col--){
			if(work[row][col] != last[row][col]){ //左上方向に向かって塗らなければならない場所を探す

				paint_state += POW[index];
				for(int a = row; a >= 0; a--){
					for(int b = col; b >= 0; b--){
						work[a][b] = last[row][col];
					}
				}
			}
			index--;
		}
	}

	at2 = STATE.find(paint_state);

	if(at2 != STATE.end()){ //塗った状態は登録されている場合

		PAINT[first_code] = paint_state;
		return STATE[paint_state];
	}

	PAINT[first_code] = paint_state; //first_codeが塗らなければならない場所を登録
	return STATE[paint_state] = state_index++;
}

void calc_states(char first_table[NUM][NUM]){

	int first_code = get_code(first_table); //最初の状態

	queue<int> Q;
	Q.push(first_code);

	int base_code,base_state,tmp_code,tmp_state,index;
	char base_table[NUM][NUM],work[NUM][NUM];

	bool check[MAX];

	for(int i = 0; i < MAX; i++){

		check[i] = false;
	}

	while(!Q.empty()){

		base_code = Q.front();
		Q.pop();

		index = 0;

		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				if(base_code & (1 << index)){
					base_table[row][col] = 'B';
				}else{
					base_table[row][col] = 'W';
				}
				index++;
			}
		}

		base_state = get_state(base_table);
		check[base_state] = true;

		//次に遷移する状態を全探索する

		int count;

		//次の状態を全て試す(最大H*W*2通り)
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				for(int a = 0; a < 2; a++){

					for(int i = 0; i < H; i++){
						for(int k = 0; k < W; k++){
							work[i][k] = base_table[i][k];
						}
					}

					count = 0;

					for(int i = row; i >= 0; i--){
						for(int k = col; k >= 0; k--){
							count++;
							work[i][k] = color[a];
						}
					}


					tmp_state = get_state(work);

					P_table[base_state][tmp_state] += 1.0/(double)(2*H*W);
					ADD_table[base_state][tmp_state] += ((row+1)*(col+1))/(double)(2*H*W);

					if(!check[tmp_state]){

						check[tmp_state] = true;
						tmp_code = get_code(work);

						index = 0;

						for(int a = 0; a < row; a++){
							for(int b = 0; b < col; b++){
								if(tmp_code & (1 << index)){

									work[a][b] = 'B';

								}else{
									work[a][b] = 'W';
								}
							}
						}

						Q.push(tmp_code);
					}
				}
			}
		}
	}
}

MATRIX gauss_jordan(MATRIX A,int SIZE){

	MATRIX C(SIZE,V(SIZE+1));

	for(int row = 0; row < SIZE; row++){
		for(int col = 0; col <= SIZE; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	for(int i = 0; i < SIZE; i++){
		base_row = i;
		for(int row = i+1; row < SIZE; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue; //操作不要

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col <= SIZE; col++){ //基準行の係数を1にする
			C[i][col] /= tmp;
		}

		for(int row = 0; row < SIZE; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue; //基準行、または該当列が0ならSKIP

			tmp = C[row][i];

			for(int col = i; col <= SIZE; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
	}

	return C;
}

void func(){

	for(int row = 0; row < H; row++){
		scanf("%s",first[row]);
	}


	for(int row = 0; row < H; row++){

		scanf("%s",last[row]);
	}

	STATE.clear();
	PAINT.clear();

	state_index = 0;

	for(int i = 0; i < MAX; i++){
		for(int k = 0; k < MAX; k++){
			P_table[i][k] = 0;
			ADD_table[i][k] = 0;
		}
	}

	calc_states(first);

	first_state = get_state(first);
	ans_state = get_state(last);

	//return;
	MATRIX A(state_index,V(state_index+1));

	for(int row = 0; row < state_index; row++){
		for(int col = 0; col <= state_index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < state_index; i++){

		A[i][i] = 1.0;

		if(i == ans_state)continue;

		for(int k = 0; k < state_index; k++){

			A[i][k] -= P_table[i][k];
			A[i][state_index] += ADD_table[i][k]; //塗る枚数
		}
	}

	A = gauss_jordan(A,state_index);

	printf("%.10lf\n",A[first_state][state_index]);

	return;
}


int main(){

	POW[0] = 1;

	for(int i = 1; i < 26; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d %d",&H,&W);
		if(H == 0&& W == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 5664
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define EPS 1e-10
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int w,h;
int fie[2][5][5];
vector<P> G[6*6*6*6*6];
int ok[6];
int curfie[5][5];
int id[10005];

void init(int v,int a,int b,int col){
	memset(curfie,-1,sizeof(curfie));
	for(int i=0;i<w;i++){
		for(int j=ok[i];j<h;j++){
			curfie[j][i]=fie[1][j][i];
		}
	}
	for(int i=0;i<=a;i++){
		for(int j=0;j<=b;j++){
			curfie[i][j]=col;
		}
	}
	int nok[6];
	for(int i=w-1;i>=0;i--){
		nok[i]=h;
		for(int j=h-1;j>=0;j--){
			if(i<w-1 && nok[i+1]==nok[i])break;
			if(curfie[j][i]!=fie[1][j][i])break;
			nok[i]--;
		}
	}
	int nxt=0;
	for(int i=w-1;i>=0;i--){
		nxt*=h+1;
		nxt+=nok[i];
	}
	G[v].push_back(P(nxt,(a+1)*(b+1)));
}


typedef vector<double> vec;
typedef vector<vec> mat;

vec gauss_jordan(const mat &A,const vec& b){
	int N=A.size();
	mat B(N,vec(N+1));
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			B[i][j]=A[i][j];
		}
	}
	for(int i=0;i<N;i++){
		B[i][N]=b[i];
	}
	for(int i=0;i<N;i++){
		int pivot=i;
		for(int j=i;j<N;j++){
			if(fabs(B[j][i])>fabs(B[pivot][i]))pivot=j;
		}
		swap(B[i],B[pivot]);
		if(fabs(B[i][i])<EPS)continue;
		for(int j=i+1;j<=N;j++){
			B[i][j]/=B[i][i];
		}
		for(int j=0;j<N;j++){
			if(i!=j){
				for(int k=i+1;k<=N;k++){
					B[j][k]-=B[j][i]*B[i][k];
				}
			}
		}
	}
	vec x(N);
	for(int i=0;i<N;i++){
		x[i]=B[i][N];
	}
	return x;
}


void solve(){
	for(int i=0;i<6*6*6*6*6;i++){
		G[i].clear();
	}
	int siz=1;
	for(int i=0;i<w;i++){
		siz*=(h+1);
	}
	int siz2=0;
	memset(id,-1,sizeof(id));
	for(int i=0;i<siz;i++){
		int v=i;
		bool flag=false;
		for(int j=0;j<w;j++){
			ok[j]=v%(h+1);
			if(j>0 && ok[j-1]<ok[j])flag=true;
			v/=h+1;
		}
		if(flag)continue;
		id[i]=siz2;
		siz2++;
		for(int a=0;a<h;a++){
			for(int b=0;b<w;b++){
				for(int c=0;c<2;c++){
					init(i,a,b,c);
				}
			}
		}
	}
	mat eff(siz2,vec(siz2,0.0));
	for(int i=0;i<siz;i++){
		if(id[i]==-1)continue;
		int v=id[i];
		if(v==0){
			eff[v][0]=1.0;
		}else{
			for(int k=0;k<G[i].size();k++){
				eff[v][id[G[i][k].first]]+=(double)1.0/G[i].size();
			}
		}
	}
	double ads=0.0;
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			ads+=(i+1.0)*(j+1.0);
		}
	}
	ads/=h*w;
	vec vo(siz2,0.0);
	for(int i=1;i<siz2;i++){
		for(int j=0;j<siz2;j++){
			eff[i][j]=-eff[i][j];
		}
		eff[i][i]+=1.0;
		vo[i]=ads;
	}
	vec res=gauss_jordan(eff,vo);
	int nok[6];
	for(int i=w-1;i>=0;i--){
		nok[i]=h;
		for(int j=h-1;j>=0;j--){
			if(i<w-1 && nok[i+1]==nok[i])break;
			if(fie[1][j][i]!=fie[0][j][i])break;
			nok[i]--;
		}
	}
	int resid=0;
	for(int i=w-1;i>=0;i--){
		resid*=h+1;
		resid+=nok[i];
	}
	printf("%.10f\n",res[id[resid]]);
}

int main(void){
	while(1){
		scanf("%d%d",&h,&w);
		if(h==0 && w==0)break;
		for(int k=0;k<2;k++){
			for(int i=0;i<h;i++){
				string str;
				cin >> str;
				for(int j=0;j<w;j++){
					if(str[j]=='W'){
						fie[k][i][j]=0;
					}else{
						fie[k][i][j]=1;
					}
				}
			}
		}
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 4416
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define EPS 1e-10
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int w,h;
int fie[2][5][5];
vector<P> G[6*6*6*6*6];
int valid[61];
int ok[6];
int curfie[5][5];
int id[10005];

void init(int v,int a,int b,int col){
	memset(curfie,-1,sizeof(curfie));
	for(int i=0;i<w;i++){
		for(int j=ok[i];j<h;j++){
			curfie[j][i]=fie[1][j][i];
		}
	}
	for(int i=0;i<=a;i++){
		for(int j=0;j<=b;j++){
			curfie[i][j]=col;
		}
	}
	int nok[6];
	for(int i=w-1;i>=0;i--){
		nok[i]=h;
		for(int j=h-1;j>=0;j--){
			if(i<w-1 && nok[i+1]==nok[i])break;
			if(curfie[j][i]!=fie[1][j][i])break;
			nok[i]--;
		}
	}
	int nxt=0;
	for(int i=w-1;i>=0;i--){
		nxt*=h+1;
		nxt+=nok[i];
	}
	G[v].push_back(P(nxt,(a+1)*(b+1)));
}


typedef vector<double> vec;
typedef vector<vec> mat;

vec gauss_jordan(const mat &A,const vec& b){
	int N=A.size();
	mat B(N,vec(N+1));
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			B[i][j]=A[i][j];
		}
	}
	for(int i=0;i<N;i++){
		B[i][N]=b[i];
	}
	for(int i=0;i<N;i++){
		int pivot=i;
		for(int j=i;j<N;j++){
			if(fabs(B[j][i])>fabs(B[pivot][i]))pivot=j;
		}
		swap(B[i],B[pivot]);
		if(fabs(B[i][i])<EPS)continue;
		for(int j=i+1;j<=N;j++){
			B[i][j]/=B[i][i];
		}
		for(int j=0;j<N;j++){
			if(i!=j){
				for(int k=i+1;k<=N;k++){
					B[j][k]-=B[j][i]*B[i][k];
				}
			}
		}
	}
	vec x(N);
	for(int i=0;i<N;i++){
		x[i]=B[i][N];
	}
	return x;
}


void solve(){
	for(int i=0;i<6*6*6*6*6;i++){
		G[i].clear();
	}
	int siz=1;
	for(int i=0;i<w;i++){
		siz*=(h+1);
	}
	int siz2=0;
	memset(id,-1,sizeof(id));
	for(int i=0;i<siz;i++){
		int v=i;
		bool flag=false;
		for(int j=0;j<w;j++){
			ok[j]=v%(h+1);
			if(j>0 && ok[j-1]<ok[j])flag=true;
			v/=h+1;
		}
		if(flag)continue;
		id[i]=siz2;
		siz2++;
		for(int a=0;a<h;a++){
			for(int b=0;b<w;b++){
				for(int c=0;c<2;c++){
					init(i,a,b,c);
				}
			}
		}
	}
	mat eff(siz2,vec(siz2,0.0));
	for(int i=0;i<siz;i++){
		if(id[i]==-1)continue;
		int v=id[i];
		if(v==0){
			eff[v][0]=1.0;
		}else{
			for(int k=0;k<G[i].size();k++){
				eff[v][id[G[i][k].first]]+=(double)1.0/G[i].size();
			}
		}
	}
	double ads=0.0;
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			ads+=(i+1.0)*(j+1.0);
		}
	}
	ads/=h*w;
	vec vo(siz2,0.0);
	for(int i=1;i<siz2;i++){
		for(int j=0;j<siz2;j++){
			eff[i][j]=-eff[i][j];
		}
		eff[i][i]+=1.0;
		vo[i]=ads;
	}
	vec res=gauss_jordan(eff,vo);
	int nok[6];
	for(int i=w-1;i>=0;i--){
		nok[i]=h;
		for(int j=h-1;j>=0;j--){
			if(i<w-1 && nok[i+1]==nok[i])break;
			if(fie[1][j][i]!=fie[0][j][i])break;
			nok[i]--;
		}
	}
	int resid=0;
	for(int i=w-1;i>=0;i--){
		resid*=h+1;
		resid+=nok[i];
	}
	printf("%.10f\n",res[id[resid]]);
}

int main(void){
	while(1){
		scanf("%d%d",&h,&w);
		if(h==0 && w==0)break;
		for(int k=0;k<2;k++){
			for(int i=0;i<h;i++){
				string str;
				cin >> str;
				for(int j=0;j<w;j++){
					if(str[j]=='W'){
						fie[k][i][j]=0;
					}else{
						fie[k][i][j]=1;
					}
				}
			}
		}
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 4492
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
#define double long double

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcountll

#define INF 1e16
#define EPS 1e-8

typedef vector<double> vec;
typedef vector<vec> mat;

vec gauss_jordan(const mat& A,const vec& b){
  int n=A.size();
  mat B(n,vec(n+1));
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      B[i][j]=A[i][j];
    }
    B[i][n]=b[i];
  }

  for (int k = 0; k < n-1; k++) {
    for (int i = k + 1; i < n; i++) {
      double d = B[i][k] / B[k][k];
      for (int j = k + 1; j <= n; j++){
        B[i][j] -= B[k][j] * d;
      }
    }
  }

  for (int i = n - 1; i >= 0; i--) {
    double d = B[i][n];
    for (int j = i + 1; j < n; j++){
      d -= B[i][j] * B[j][n];
    }
    B[i][n] = d / B[i][i];
  }

  vec x(n);
  for(int i=0;i<n;i++)x[i]=B[i][n];
  return x;
}

int H,W,N;
vector<vector<int> > ps;
vector<int> crt;
vector<string> sb,tb;
double p;

vector<int> calc(const vector<string>& a){
  vector<int> res;
  int mn=H;
  for(int j=W-1;j>=0;j--){
    int tmp=0;
    for(int i=H-1;i>=0;i--){
      if(tb[i][j]!=a[i][j]){
        break;
      }
      tmp++;
    }
    minch(mn,tmp);
    res.push_back(mn);
  }
  reverse(all(res));
  return res;
}

void predfs(int i,int j){
  if(i==W){
    ps.push_back(crt);
    return ;
  }
  repl(k,j,H+1){
    crt.push_back(k);
    predfs(i+1,k);
    crt.pop_back();
  }
}
void dfs(int i0,int j0,mat& A,vec &b){
  if(i0==W){
    vector<string> crtb;
    crtb.resize(H);
    rep(i,H)crtb[i]=tb[i];
    rep(j,W){
      rep(i,H-crt[j])crtb[i][j]='.';
    }
    int crtidx=lower_bound(all(ps),crt)-ps.begin();
    rep(i,H)rep(j,W)rep(c,2){
      vector<string> tmp(H);
      rep(ni,H)tmp[ni]=crtb[ni];
      rep(ni,i+1)rep(nj,j+1){
        if(c==0) tmp[ni][nj]='W';
        else tmp[ni][nj]='B';
      }
      int nxtidx=lower_bound(all(ps),calc(tmp))-ps.begin();
      A[crtidx][nxtidx]-=p; b[crtidx]+=p*(double)(i+1)*(double)(j+1);
    }
    return ;
  }
  repl(k,j0,H+1){
    crt.push_back(k);
    dfs(i0+1,k,A,b);
    crt.pop_back();
  }
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  while(1){
    cin>>H>>W;
    if(H==0)break;

    ps.clear(); p=1.0/(double)(H*W*2.0);
    sb.resize(H); tb.resize(H);

    rep(i,H)cin>>sb[i];
    rep(i,H)cin>>tb[i];

    predfs(0,0);
    N=ps.size();
    mat A(N,vec(N,0)); vec b(N,0.0);
    dfs(0,0,A,b);

    int startidx=lower_bound(all(ps),calc(sb))-ps.begin();
    int endidx=lower_bound(all(ps),calc(tb))-ps.begin();
    rep(i,N)A[i][i]+=1.0;
    rep(j,N)A[endidx][j]=0.0;
    A[endidx][endidx]=1.0; b[endidx]=0.0;
    vec res=gauss_jordan(A,b);
    printf("%.10Lf\n", res[startidx]);
  }

  return 0;
}
accuracy: 1
time_ms: 720
memory_kb: 5164
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
typedef vector<int> vi;

typedef vector<double> vd;
typedef vector<vd> mat;
double eps=1e-9;
int MAX_H=252;
vd solve(mat a,vd b){
	int H=a.size(),W=a[0].size();
	bool used[MAX_H]={};
	rep(j,W){
		int i=0;
		while(i<H&&(used[i]||abs(a[i][j])<eps)) i++;
		if(i==H) continue;
		used[i]=1;
//		rep(x,H) rep(y,W) printf("a[%d][%d]=%lf\n",x,y,a[x][y]);
		double t=a[i][j];
		rep(k,W) a[i][k]/=t;
		b[i]/=t;
		rep(k,H){
			if(k==i) continue;
			double c=-a[k][j]/a[i][j];
			rep(l,W) a[k][l]+=a[i][l]*c;
			b[k]+=b[i]*c;
		}
	}
	return b;
}

int H,W,I;
string s[5],t[5];
vi brd[252];
map<vi,int> ibrd;
void dfs(int h,int w,vector<int> vc){
	if(h==H){
		brd[I]=vc;
		ibrd[vc]=I;
		I++;
		return;
	}
	rep(i,w+1){
		vector<int> nvc=vc;
		nvc.pb(i);
		dfs(h+1,i,nvc);
	}
}
void init(){
	I=0;
	ibrd.clear();
}
vector<string> paint(vector<string> a,int x,int y,char c){
	rep(i,x+1) rep(j,y+1) a[i][j]=c;
	return a;
}
int main(){
	while(true){
		cin>>H>>W;
		int X=H*W*2;
		if(H==0) break;
		rep(i,H) cin>>s[i];
		rep(i,H) cin>>t[i];
		init();
		dfs(0,W,vector<int>());
		mat M;
		vd con;
		rep(i,I){
			vd eq(I);
			double co=0;
			if(i==0){
				eq[i]=1;
				M.pb(eq);
				con.pb(co);
				continue;
			}
			eq[i]=-1;
			vi v=brd[i];
			vector<string> a(H,string(W,'a'));
			rep(x,H) rep(y,W) a[x][y]=t[x][y];
			rep(x,H) rep(y,v[x]) a[x][y]='*';
			rep(x,H) rep(y,W) rep(z,2){
				char c='B';
				if(z==1) c='W';
				vector<string> b=paint(a,x,y,c);
				vector<int> nv;
				rep(j,H){
					int k=W-1;
					while(k>=0&&b[j][k]==t[j][k]) k--;
					nv.pb(k+1);
				}
				for(int j=H-1;j>0;j--) chmax(nv[j-1],nv[j]);
				int ni=ibrd[nv];
				eq[ni]+=1.0/X;
				co-=(double)(x+1)*(y+1)/X;
			}
			M.pb(eq);
			con.pb(co);
		}
		vd ans=solve(M,con);
		vector<int> fv;
		rep(j,H){
			int k=W-1;
			while(k>=0&&s[j][k]==t[j][k]) k--;
			fv.pb(k+1);
		}
		for(int j=H-1;j>0;j--) chmax(fv[j-1],fv[j]);
		int id=ibrd[fv];
		printf("%.12f\n",ans[id]);
	}
}
accuracy: 1
time_ms: 440
memory_kb: 4048
final_rank: 12

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const double EPS=1e-8;
typedef vector<double>vec;
typedef vector<vec>mat;
inline double ABS(double a){return max(a,-a);}
vec gauss_jordan(const mat &A,const vec &b){
	int n=A.size();
	mat B(n,vec(n+1));
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)B[i][j]=A[i][j];
	for(int i=0;i<n;i++)B[i][n]=b[i];
	for(int i=0;i<n;i++){
		int pivot=i;
		for(int j=i;j<n;j++){
			if(ABS(B[j][i])>ABS(B[pivot][i]))pivot=j;
		}
		swap(B[i],B[pivot]);
		if(ABS(B[i][i])<EPS)break;
		for(int j=i+1;j<=n;j++)B[i][j]/=B[i][i];
		for(int j=0;j<n;j++){
			if(i!=j){
				for(int k=i+1;k<=n;k++)B[j][k]-=B[j][i]*B[i][k];
			}
		}
	}
	vec x(n);
	for(int i=0;i<n;i++)x[i]=B[i][n];
	return x;
}
char sA[7][7];
char sB[7][7];
vector<int>v[400];
map<vector<int>,int>m;
int sz;
int perm[7];
int h,w;
void calc(int a,int b){
	if(a==h){
		vector<int>tmp;
		for(int j=0;j<a;j++)tmp.push_back(perm[j]);
		v[sz]=tmp;
		m[tmp]=sz++;
		return;
	}
	for(int i=b;i<=w;i++){
		perm[a]=i;
		calc(a+1,i);
	}
}
int t[7][7];
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		h=a;w=b;
		for(int i=0;i<a;i++)scanf("%s",sA+i);
		for(int i=0;i<a;i++)scanf("%s",sB+i);
		m.clear();
		sz=0;
		calc(0,0);
		//printf("%d\n",sz);
		mat A(sz,vec(sz));
		vec B(sz);
		for(int i=0;i<sz;i++){
			if(v[i][0]==w){
				A[i][i]=1;
				continue;
			}
			A[i][i]=a*b*2;
			for(int j=1;j<=a;j++)for(int k=1;k<=b;k++){
				B[i]+=j*k;
				for(int x=0;x<a;x++)for(int y=0;y<b;y++)t[x][y]=0;
				for(int l=0;l<a;l++)for(int o=0;o<v[i][l];o++)t[l][b-1-o]=1;
				for(int x=0;x<j;x++)for(int y=0;y<k;y++){
					if(sB[x][y]=='B')t[x][y]=1;
					else t[x][y]=0;
				}
				vector<int>to(a);
				for(int l=a-1;l>=0;l--){
					int r=0;
					for(int o=b-1;o>=0;o--){
						if(!t[l][o])break;
						r++;
					}
					if(l<a-1)r=min(r,to[l+1]);
					to[l]=r;
				}
				int tv=m[to];
				A[i][tv]-=1;
			}
			for(int j=1;j<=a;j++)for(int k=1;k<=b;k++){
				B[i]+=j*k;
				for(int x=0;x<a;x++)for(int y=0;y<b;y++)t[x][y]=0;
				for(int l=0;l<a;l++)for(int o=0;o<v[i][l];o++)t[l][b-1-o]=1;
				for(int x=0;x<j;x++)for(int y=0;y<k;y++){
					if(sB[x][y]=='W')t[x][y]=1;
					else t[x][y]=0;
				}
				vector<int>to(a);
				for(int l=a-1;l>=0;l--){
					int r=0;
					for(int o=b-1;o>=0;o--){
						if(!t[l][o])break;
						r++;
					}
					if(l<a-1)r=min(r,to[l+1]);
					to[l]=r;
				}
				int tv=m[to];
				A[i][tv]-=1;
			}
		}
	//	for(int i=0;i<sz;i++){
		//	for(int j=0;j<sz;j++)printf("%.2f ",A[i][j]);
	//		printf("%.2f\n",B[i]);
		//}
		vec x=gauss_jordan(A,B);
		
		vector<int>ans(a);
		for(int i=a-1;i>=0;i--){
			int r=0;
			for(int j=b-1;j>=0;j--){
				if(sB[i][j]!=sA[i][j])break;
				r++;
			}
			if(i<a-1)r=min(r,ans[i+1]);
			ans[i]=r;
		}
		printf("%.12f\n",x[m[ans]]);
	}
}
accuracy: 1
time_ms: 300
memory_kb: 2060
final_rank: 5

code_snippet: //Name: Overwriting Game
//Level: 5
//Category: 確率,期待値,数学,Math,分割数,ヤング図形,方程式
//Note:

/**
 * セルを選ぶと左上の領域が必ず塗りつぶされてしまうので、状態として意味があるのは
 * ・一番下から右上にかけて、目的の色が階段状に連続しているマスの並び
 * のみである。
 * 各行に着目すると、このようなマスは全て右詰めで配置されており、かつその数は直下の行以下になることがわかる
 * （直下より多くのマスが目的の色になっていても、その下のマスを塗り替えるときに巻き込まれる）。
 *
 * このような形はヤング図形と呼ばれており、この問題の規模であればあまり個数がなく（O(W^H)、実際には200個程度？）、探索で列挙することができる。
 * これを利用して、「ある状態からゴールまで持っていくときのスコアの期待値」が行列形式で書けるので、方程式を解けばよい。
 *
 * 数がかなり大きくなったり小さくなったりするので、ガウスの消去法を使うときは適切にピボットを選ばないとWAになる。
 *
 * オーダーは O((W^H)^3)。
 */

#include <iostream>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <array>
#include <cassert>

using namespace std;

const double EPS = 1e-9;

int H, W;
map<vector<int>,int> dict;
map<int,vector<int>> rev_dict;

// ヤング図形の列挙
void dfs(int prev, vector<int> &buf) {
    if(buf.size() == H) {
        const int idx = dict.size();
        dict[buf] = idx;
        rev_dict[idx] = buf;
    } else {
        for(int i = prev; i <= W; ++i) {
            buf.push_back(i);
            dfs(i, buf);
            buf.pop_back();
        }
    }
}

array<array<int,5>,5> field, goal;

int calc_idx() {
    vector<int> buf(H);
    for(int r = H-1; r >= 0; --r) {
        int cnt = 0;
        for(int c = W-1; c >= 0; --c) {
            if(field[r][c] != goal[r][c]) break;
            ++cnt;
        }
        buf[r] = cnt;
        if(r+1 < H) buf[r] = min(buf[r], buf[r+1]);
    }
    assert(dict.count(buf));
    return dict[buf];
}

// 塗りつぶしのシミュレーション
int paint(int from, int pr, int pc, int color) {
    const vector<int> &young = rev_dict[from];
    for(int r = 0; r < H; ++r) {
        for(int c = 0; c < W; ++c) {
            if(c < W-young[r]) field[r][c] = -1;
            else field[r][c] = goal[r][c];
        }
    }

    for(int r = 0; r <= pr; ++r) {
        for(int c = 0; c <= pc; ++c) {
            field[r][c] = color;
        }
    }
    return calc_idx();
}

bool solve() {
    if(!(cin >> H >> W)) return false;
    if(!H && !W) return false;

    {
        dict.clear();
        rev_dict.clear();
        vector<int> buf;
        dfs(0, buf);
    }
    for(int i = 0; i < H; ++i) {
        string s;
        cin >> s;
        for(int j = 0; j < W; ++j) {
            field[i][j] = (s[j] == 'B');
        }
    }

    for(int i = 0; i < H; ++i) {
        string s;
        cin >> s;
        for(int j = 0; j < W; ++j) {
            goal[i][j] = (s[j] == 'B');
        }
    }
    const vector<int> gy(H, W);
    const int init = calc_idx();
    const int target = dict[gy];

    const int N = dict.size();
    // 期待値ベクトルの最後の要素は定数
    vector<vector<double>> mat(N, vector<double>(N+1, 0));
    for(int from = 0; from < N; ++from) {
        for(int r = 0; r < H; ++r) {
            for(int c = 0; c < W; ++c) {
                for(int color = 0; color < 2; ++color) {
                    const int to = paint(from, r, c, color);
                    mat[from][to] += 1.0 / (H*W*2);
                    mat[from][N] -= (r+1)*(c+1) / double(H*W*2);
                }
            }
        }
    }
    for(int r = 0; r < N; ++r) {
        mat[r][r] -= 1.0;
    }
    for(int c = 0; c < N+1; ++c) {
        if(c != target) mat[target][c] = 0;
    }
    /*
    for(int r = 0; r < N; ++r) {
        for(int c = 0; c < N+1; ++c) {
            cout << mat[r][c] << ' ';
        }
        cout << endl;
    }
    */

    // Gaussian elimination
    vector<bool> done(N, false);
    for(int i = 0; i < N; ++i) {
        // ピボットを探す
        int pivr;
        double pivv = 0.0;
        for(int r = 0; r < N; ++r) {
            if(done[r]) continue;
            if(fabs(mat[r][i]) > fabs(pivv)) {
                pivr = r;
                pivv = mat[r][i];
            }
        }
        if(fabs(pivv) < EPS) continue;

        // ピボットのいる列を掃き出す
        for(int r = 0; r < N; ++r) {
            if(r == pivr) continue;
            const double ratio = mat[r][i] / pivv;
            for(int c = 0; c < N+1; ++c) {
                mat[r][c] -= mat[pivr][c] * ratio;
            }
        }
        done[pivr] = true;
    }
    
    double ans = 1.0 / 0.0;
    for(int r = 0; r < N; ++r) {
        if(fabs(mat[r][init]) > EPS) {
            ans = fabs(mat[r][N] / mat[r][init]);
            break;
        }
    }
    cout << ans << endl;
    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);
    cout.setf(ios::fixed);
    cout.precision(10);

    while(solve()) ;
    return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 1792
final_rank: 8

code_snippet: #include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-8;

const int N_MAX=252;

bool Gauss_Jordan(int n,const double A[N_MAX][N_MAX],const double *b,double *x){
	static double B[N_MAX][N_MAX+1];
	rep(i,n){
		rep(j,n) B[i][j]=A[i][j];
		B[i][n]=b[i];
	}

	rep(i,n){
		int piv=i;
		for(int j=i;j<n;j++) if(abs(B[j][i])>abs(B[piv][i])) piv=j;
		rep(j,n+1) swap(B[i][j],B[piv][j]);

		if(abs(B[i][i])<EPS) return false;

		for(int j=i+1;j<=n;j++) B[i][j]/=B[i][i];
		rep(j,n) if(i!=j) for(int k=i+1;k<=n;k++) B[j][k]-=B[j][i]*B[i][k];
	}

	rep(i,n) x[i]=B[i][n];
	return true;
}

int H,W;
char B0[5][6],B1[5][6];

struct state{
	char B[5][5];
	bool operator==(const state &s)const{
		rep(i,H) rep(j,W) if(B[i][j]!=s.B[i][j]) return false;
		return true;
	}
};

void dfs(int y,int x,state &s,vector<state> &S){
	if(x==-1){
		S.push_back(s);
		return;
	}

	for(int i=y;i<=H;i++){
		for(int k=0;k<i;k++) s.B[k][x]='?';
		if(i>y) s.B[i-1][x]='x';
		for(int k=i;k<H;k++) s.B[k][x]='o';
		dfs(i,x-1,s,S);
	}
}

state board_to_state(const char B[5][6]){
	state s;
	rep(i,H) rep(j,W) {
		if(B[i][j]==B1[i][j]) s.B[i][j]='o';
		else                  s.B[i][j]='x';
	}
	int len=7777777;
	for(int i=H-1;i>=0;i--){
		int j;
		for(j=W-1;j>=0;j--) if(s.B[i][j]=='x' || W-j>len) break;
		if(W-j<=len){
			len=W-j-1;
			j--;
		}
		for(;j>=0;j--) s.B[i][j]='?';
	}
	return s;
}

int main(){
	for(;scanf("%d%d",&H,&W),H;){
		rep(i,H) scanf("%s",B0[i]);
		rep(i,H) scanf("%s",B1[i]);

		vector<state> S; // set of possible states
		state s;
		dfs(0,W-1,s,S);

		int m=S.size();
		static double P[252][252]; // transition matrix, P[i][j] := (probability to transit from state i to j)
		static double C[252][252]; // coefficient for b
		rep(i,m) rep(j,m) P[i][j]=C[i][j]=0;
		rep(k,m){
			rep(i,H) rep(j,W) rep(c,2) { // operate (i, j) with color c
				char B[5][6];
				rep(y,H) rep(x,W) {
					if     (S[k].B[y][x]=='o') B[y][x]=B1[y][x];
					else if(S[k].B[y][x]=='x') B[y][x]=(B1[y][x]=='W'?'B':'W');
					else                       B[y][x]='?';
				}
				rep(y,i+1) rep(x,j+1) B[y][x]=(c==0?'W':'B');

				state s=board_to_state(B);
				int to=find(S.begin(),S.end(),s)-S.begin();
				P[k][to]+=1/(H*W*2.0);
				C[k][to]+=(i+1)*(j+1)/(H*W*2.0);
			}
		}

		int i0=find(S.begin(),S.end(),board_to_state(B0))-S.begin();
		int i1=find(S.begin(),S.end(),board_to_state(B1))-S.begin();

		static double A[252][252];
		double b[252]={},x[252];
		rep(i,m){
			if(i==i1){
				b[i]=0;
				rep(j,m) A[i][j]=(i==j?1:0);
			}
			else{
				rep(j,m){
					A[i][j]=(i==j?1:0)-P[i][j];
					b[i]+=C[i][j];
				}
			}
		}

		Gauss_Jordan(m,A,b,x);

		printf("%.9f\n",x[i0]);
	}

	return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 3084
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;
int H, W;
void input(int grid[5][5]){
    REP(y, H) {
        string s;
        cin >> s;
        REP(x, W) {
            grid[y][x] = (s[x] == 'B');
        }
    }
}
const double EPS = 1e-8;
typedef vector<double> Vec;
typedef vector<Vec> Mat;

Vec gauss_jordan(const Mat& A, const Vec& b){
    int W = A[0].size();
    int H = A.size();

    Mat B(H, Vec(W + 1));
    for(int y = 0; y < H; y++)
        for(int x = 0; x < W; x++)
            B[y][x] = A[y][x];
    for(int y = 0; y < H; y++)
        B[y][W] = b[y];

    bool unique = true; // 解が一意かどうか
    int cy = 0; // 現在注目している式

    // 現在注目している変数
    for(int x = 0; x < W; x++){
        int pivot = cy;
        // 注目している変数の係数の絶対値が一番大きい式を選ぶ
        for(int y = cy; y < H; y++){
            if(abs(B[y][x]) > abs(B[pivot][x])) pivot = y;
        }

        // 解が一意でないか，解が存在しない
        if(pivot >= H || abs(B[pivot][x]) < EPS) {
            unique = false;
            continue;
        }

        swap(B[cy], B[pivot]);

        // 注目している変数の係数を1にする
        for(int x2 = x + 1; x2 <= W; x2++) {
            B[cy][x2] /= B[cy][x];
        }

        // y番目の式からx2番目の変数を消去
        for(int y = 0; y < H; y++) if(y != cy)
            for(int x2 = x + 1; x2 <= W; x2++)
                B[y][x2] -= B[y][x] * B[cy][x2];

        // 次の式に注目する
        cy++;
    }


    // 解が存在するかどうか
    for(int y = cy; y < H; y++)
        if(abs(B[y][W]) > EPS)
            return Vec();

    // 解が複数存在するかどうか
    if(!unique) return Vec();

    // 一意な解を返す
    Vec V(W);
    int cur_x = 0;
    for(int y = 0; y < H; y++){
        if(abs(B[y][cur_x]) > EPS){
            V[cur_x++] = B[y][W];
        }
    }
    return V;
}

vector<int> calc_v(int grid[5][5], int goal[5][5]){
    vector<int> v;
    REP(y, H) {
        int cx = W;
        while(cx - 1 >= 0 && grid[y][cx - 1] == goal[y][cx - 1]){
            cx--;
        }
        v.push_back(W - cx);
    }
    for(int y = H - 2; y >= 0; y--){
        v[y] = min(v[y], v[y + 1]);
    }
    return v;
}

void calc_grid(vector<int> v, int grid[5][5], int goal[5][5]){
    REP(y, H) REP(x, W) grid[y][x] = 2;
    REP(y, H) {
        REP(x, v[y]) {
            grid[y][W - 1 - x] = goal[y][W - 1 - x];
        }
    }
}

int main(){
    while(cin >> H >> W && (H > 0)){
        int start[5][5] = {};
        int goal[5][5] = {};
        input(start);
        input(goal);

        vector<int> goal_v = calc_v(goal, goal);
        vector<int> start_v = calc_v(start, goal);
        if(start_v == goal_v){
            cout << 0 << endl;
            continue;
        }

        vector<vector<int>> list;
        map<vector<int>, int> index;
        REP(S, 1 << (H + W)){
            if(__builtin_popcount(S) != H) continue;
            int cy = 0, cx = 0;
            vector<int> v;
            REP(i, H + W){
                if(S >> i & 1){
                    v.push_back(cx);
                    cy++;
                }else{
                    cx++;
                }
            }
            if(v == goal_v) continue;

            int idx = index.size();
            index[v] = idx;
            list.push_back(v);
            assert(list[idx] == v);
        }

        int N = list.size();
        Mat M(N, Vec(N));
        Vec B(N);
        REP(i, N) {
            M[i][i] = -1.0;
            double T = 1.0 * H * W * 2;
            REP(ry, H) REP(rx, W) REP(c, 2) {
                int grid[5][5];
                calc_grid(list[i], grid, goal);
                REP(y, ry + 1) REP(x, rx + 1) {
                    grid[y][x] = c;
                }
                vector<int> nv = calc_v(grid, goal);

                int cost = (ry + 1) * (rx + 1);
                B[i] -= cost / T;


                if(nv == goal_v){
                    continue;
                }

                int j = index[nv];
                M[i][j] += 1.0 / T;
            }
        }

        Vec C = gauss_jordan(M, B);
        printf("%.12f\n", C[ index[ start_v ] ]);
    }
    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 2316
final_rank: 7