Problem:
Problem E : Connect
r
×
c
のグリッドが与えられる。
グリッドのいくつかのマスには1から8までの数字が書かれている。
数字が書かれているマスと他の数字が書かれているマスを線で結ぶ必要がある。
数字が書かれているマスについて、そのマスに書かれている本数だけ、他のマスとの間に線を結ぶ必要がある。
ただし、線を結べるのは上下左右方向だけで、一つの方向について、最大２本までである。
他の数字を跨いで線で結ぶことはできない。
また、次のように交差してしまう結び方をすることはできない。
グリッドが入力として与えられるので、数字が書かれているマス全てを正しく結ぶ方法が、何通りあるのかを数えて欲しい。
Input
入力は以下のフォーマットで与えられる。
r
c
grid
1
.
.
.
grid
r-1
grid
i
は長さcの文字列で、1から8までの数字か"."からなる。
入力は以下の制約を満たす
1 ≤
r,c
≤ 10
Output
答えの値を100,000,007で割った余りを1行に出力せよ
Sample Input 1
3 3
.1.
1.1
.1.
Sample Output 1
0
Sample Input 2
1 3
1.1
Sample Output 2
1
Sample Input 3
3 3
4.2
...
2..
Sample Output 3
1
Sample Input 4
7 7
2.3.1.1
.......
2......
.......
..3.3..
.......
2.2.4.3
Sample Output 4
10

Submitted solutions:

code_snippet: // AOJ #1504 Connect
// 2025.4.2

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 100000007;

int dp[2][3][60005];
int d[11];

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

    int H, W;
    cin >> H >> W;
    char grid[11][11];
    for(int i=0; i<H; i++) cin >> grid[i];

    d[0] = 1;
    for(int i = 0; i < W; i++) d[i+1] = d[i] * 3;
    int maxProfile = d[W];

    dp[0][0][0] = 1;
    int cur = 0, nxt = 1;

    for(int i = 0; i < H; i++){
        for(int j = 0; j < W; j++){
            memset(dp[nxt], 0, sizeof(dp[nxt]));
            for(int carry = 0; carry < 3; carry++){
                for(int prof = 0; prof < maxProfile; prof++){
                    if(dp[cur][carry][prof] == 0) continue;
                    int ways = dp[cur][carry][prof];
                    int s = (prof / d[j]) % 3;
                    if(grid[i][j] == '.'){
                        if(carry && s) continue;
                        if(carry && j == W - 1) continue;
                        dp[nxt][carry][prof] = (dp[nxt][carry][prof] + ways) % MOD;
                    } else {
                        int num = grid[i][j] - '0';
                        for(int u = 0; u < 3; u++){
                            int t = num - carry - s - u;
                            if(t < 0 || t > 2) continue;
                            if(u && j == W - 1) continue;
                            int newProf = prof + d[j] * (t - s);
                            dp[nxt][u][newProf] = (dp[nxt][u][newProf] + ways) % MOD;
                        }
                    }
                }
            }
            cur ^= 1;
            nxt ^= 1;
        }
    }
    cout << dp[cur][0][0] << endl;
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 4860
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <stack>
#include  <map>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=100000007;
int dp[10][10][3][60000];
int pow3[13];
string s[10];
int h,w;
int dfs(int x,int y,int r,int zhuan)
{
    if(x==h){
        return zhuan==0;
    }
    if(y==w){
        if(r) return 0;
        else return dfs(x+1,0,0,zhuan);
    }
    if(dp[x][y][r][zhuan]!=-1) return dp[x][y][r][zhuan];
    int tmp=zhuan/pow3[y]%3;
    if(s[x][y]=='.'){
        if(r&&tmp) return dp[x][y][r][zhuan]=0;
        else return dp[x][y][r][zhuan]=dfs(x,y+1,r,zhuan);
    }
    else{
        int need=s[x][y]-'0';
        need-=r+tmp;
        zhuan-=pow3[y]*tmp;
        int ans=0;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i+j!=need) continue;
                ans+=dfs(x,y+1,i,zhuan+pow3[y]*j);
                if(ans>maxn) ans-=maxn;
            }
        }
        return dp[x][y][r][zhuan+pow3[y]*tmp]=ans;
    }
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    cin>>h>>w;
    for(int i=0;i<h;i++){
        cin>>s[i];
    }
    pow3[0]=1;
    for(int i=1;i<13;i++) pow3[i]=pow3[i-1]*3;
    memset(dp,-1,sizeof dp);
    cout<<dfs(0,0,0,0)<<endl;
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 73544
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <stack>
#include  <map>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=100000007;
int dp[10][10][3][60000];
int pow3[13];
string s[10];
int h,w;
int dfs(int x,int y,int r,int zhuan)
{
    if(x==h){
        return zhuan==0;
    }
    if(y==w){
        if(r) return 0;
        else return dfs(x+1,0,0,zhuan);
    }
    if(dp[x][y][r][zhuan]!=-1) return dp[x][y][r][zhuan];
    if(s[x][y]=='.'){
        if(r&&zhuan/pow3[y]%3) return 0;
        else return dfs(x,y+1,r,zhuan);
    }
    else{
        int need=s[x][y]-'0';
        int tmp=zhuan/pow3[y]%3;
        need-=r+tmp;
        zhuan-=pow3[y]*tmp;
        int ans=0;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i+j!=need) continue;
                ans+=dfs(x,y+1,i,zhuan+pow3[y]*j);
                if(ans>maxn) ans-=maxn;
            }
        }
        return dp[x][y][r][zhuan]=ans;
    }
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    cin>>h>>w;
    for(int i=0;i<h;i++){
        cin>>s[i];
    }
    pow3[0]=1;
    for(int i=1;i<13;i++) pow3[i]=pow3[i-1]*3;
    memset(dp,-1,sizeof dp);
    cout<<dfs(0,0,0,0)<<endl;
    return 0;
}
accuracy: 0.3333333333333333
time_ms: 10
memory_kb: 73524
final_rank: 20

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


#define MOD 100000007
#define SIZE 13

enum Type{
	Right,
	Under,
};

struct LOC{
	LOC(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

int H,W;
char table[SIZE][SIZE];
ll POW[SIZE];
vector<LOC> ADJ[SIZE][SIZE][2];
ll dp[SIZE][SIZE][177147];



ll makeCode(ll rest[SIZE],ll to_right){

	ll ret = to_right*POW[W];
	for(int col = 0; col < W; col++){

		ret += POW[col]*rest[col];
	}

	return ret;
}



//dp[行][列][状態] := 場合の数

ll recursive(int row,int col,ll rest[SIZE],ll to_right){

	ll tmp_code = makeCode(rest,to_right);
	if(dp[row][col][tmp_code] != -1){

		return dp[row][col][tmp_code];
	}

	ll next_rest[SIZE];

	if(col == W){

		if(row == H-1){

			bool FLG = true;
			for(int i = 0; i < W; i++){
				if(rest[i] > 0){

					FLG = false;
					break;
				}
			}

			if(FLG){

				return 1;

			}else{

				return 0;
			}

		}else{ //次の行の準備

			for(int i = 0; i < W; i++){
				if(table[row+1][i] == '.'){

					next_rest[i] = rest[i];

				}else{

					next_rest[i] = (table[row+1][i]-'0')-rest[i];
				}
			}

			return dp[row][col][tmp_code] = recursive(row+1,0,next_rest,0);
		}
	}

	if(table[row][col] == '.'){

		return dp[row][col][tmp_code] = recursive(row,col+1,rest,to_right);
	}

	if(rest[col] >= 5){

		return dp[row][col][tmp_code] = 0;
	}

	ll ret = 0;

	int next_col;
	bool right_FLG = true;

	if(ADJ[row][col][Right].size() == 0){ //右に相手なし

		right_FLG = false;

	}else{ //右に相手あり

		next_col = ADJ[row][col][Right][0].col;
		for(int k = col+1; k <= next_col-1; k++){ //この区間は全て"."であるはず
			if(rest[k] > 0){ //★線分の交差が起きるので不可★

				right_FLG = false;
				break;
			}
		}
	}

	if(!right_FLG && rest[col] > 0){ //右に線分を伸ばせない,かつ残量あり

		if(rest[col] >= 3){

			return dp[row][col][tmp_code] = 0;
		}

		if(ADJ[row][col][Under].size() == 0){ //下に伸ばす相手なし

			return dp[row][col][tmp_code] = 0;
		}

		int next_row = ADJ[row][col][Under][0].row;
		if(rest[col] > table[next_row][col]-'0'){ //下に伸ばす相手の最大容量を超過

			return dp[row][col][tmp_code] = 0;
		}
	}


	ll maximum = min(rest[col],2LL);
	if(!right_FLG){

		maximum = 0;
	}

	for(ll to_r = 0; to_r <= maximum; to_r++){ //右に伸ばす数の走査


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

			next_rest[i] = rest[i];
		}

		if(to_r == 0){

			//Do nothing

		}else{ //交差しない、かつ相手あり

			if(to_r > rest[next_col])break;

			next_rest[col] = rest[col]-to_r;
			next_rest[next_col] = rest[next_col]-to_r;
		}


		if(next_rest[col] > 0){

			if(next_rest[col] >= 3)continue;

			if(ADJ[row][col][Under].size() == 0){ //下に伸ばす相手なし

				continue;
			}

			int next_row = ADJ[row][col][Under][0].row;
			if(next_rest[col] > table[next_row][col]-'0'){ //下に伸ばす相手の最大容量を超過

				continue;
			}
		}

		ret += recursive(row,col+1,next_rest,to_r);
		ret %= MOD;
	}

	return dp[row][col][tmp_code] = ret;
}


int main(){

	POW[0] = 1;
	for(int i = 1; i < SIZE; i++){

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

	scanf("%d %d",&H,&W);

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

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

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] == '.')continue;

			//右
			for(int k = col+1; k < W; k++){
				if(table[row][k] != '.'){
					ADJ[row][col][Right].push_back(LOC(row,k));
					break;
				}
			}
			//下
			for(int k = row+1; k < H; k++){
				if(table[k][col] != '.'){
					ADJ[row][col][Under].push_back(LOC(k,col));
					break;
				}
			}
		}
	}

	for(int row = 0; row <= H; row++){
		for(int col = 0; col <= W; col++){
			for(int state = 0; state < POW[W+2]; state++){

				dp[row][col][state] = -1;
			}
		}
	}

	ll first_rest[SIZE];
	for(int col = 0; col < W; col++){

		if(table[0][col] == '.'){

			first_rest[col] = 0;

		}else{

			first_rest[col] = table[0][col]-'0';
		}
	}

	printf("%lld\n",recursive(0,0,first_rest,0));

	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 201156
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 1000000000000000000
//#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define MOD 100000007
#define SIZE 13

enum Type{
	Right,
	Under,
};

struct LOC{
	LOC(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

int H,W;
char table[SIZE][SIZE];
ll POW[SIZE];
vector<LOC> ADJ[SIZE][SIZE][2];
ll dp[SIZE][SIZE][177147];



ll makeCode(ll rest[SIZE],ll to_right){

	ll ret = to_right*POW[W];
	for(int col = 0; col < W; col++){

		ret += POW[col]*rest[col];
	}

	return ret;
}


/*void print_rest(ll rest[SIZE]){

	for(int col = 0; col < W; col++){

		printf("rest[%d]:%lld\n",col,rest[col]);
	}
}*/


//dp[行][列][状態] := 場合の数

ll recursive(int row,int col,ll rest[SIZE],ll to_right){

	/*printf("row:%d col:%d\n",row,col);
	print_rest(rest);*/

	ll tmp_code = makeCode(rest,to_right);
	if(dp[row][col][tmp_code] != -1){

		return dp[row][col][tmp_code];
	}

	ll next_rest[SIZE];

	if(col == W){

		if(row == H-1){

			bool FLG = true;
			for(int i = 0; i < W; i++){
				if(rest[i] > 0){

					FLG = false;
					break;
				}
			}

			if(FLG){

				return 1;

			}else{

				return 0;
			}

		}else{ //次の行の準備

			for(int i = 0; i < W; i++){
				if(table[row+1][i] == '.'){

					next_rest[i] = rest[i];

				}else{

					next_rest[i] = (table[row+1][i]-'0')-rest[i];
				}
			}

			return dp[row][col][tmp_code] = recursive(row+1,0,next_rest,0);
		}
	}

	if(table[row][col] == '.'){

		return dp[row][col][tmp_code] = recursive(row,col+1,rest,to_right);
	}

	if(rest[col] >= 5){

		return dp[row][col][tmp_code] = 0;
	}

	ll ret = 0;

	int next_col;
	bool right_FLG = true;

	if(ADJ[row][col][Right].size() == 0){ //右に相手なし

		//printf("右に相手なし\n");

		right_FLG = false;

	}else{ //右に相手あり

		next_col = ADJ[row][col][Right][0].col;
		for(int k = col+1; k <= next_col-1; k++){ //この区間は全て"."であるはず
			if(rest[k] > 0){ //★線分の交差が起きるので不可★

				//printf("交差\n");
				right_FLG = false;
				break;
			}
		}
	}

	if(!right_FLG && rest[col] > 0){ //右に線分を伸ばせない,かつ残量あり

		if(rest[col] >= 3){

			return dp[row][col][tmp_code] = 0;
		}

		if(ADJ[row][col][Under].size() == 0){ //下に伸ばす相手なし

			return dp[row][col][tmp_code] = 0;
		}

		int next_row = ADJ[row][col][Under][0].row;
		if(rest[col] > table[next_row][col]-'0'){ //下に伸ばす相手の最大容量を超過

			return dp[row][col][tmp_code] = 0;
		}
	}


	ll maximum = min(rest[col],2LL);
	if(!right_FLG){

		maximum = 0;
	}

	//printf("maximum:%lld\n",maximum);

	for(ll to_r = 0; to_r <= maximum; to_r++){ //右に伸ばす数の走査


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

			next_rest[i] = rest[i];
		}

		if(to_r == 0){

			//Do nothing

		}else{ //交差しない、かつ相手あり

			if(to_r > rest[next_col])break;

			next_rest[col] = rest[col]-to_r;
			next_rest[next_col] = rest[next_col]-to_r;
		}


		if(next_rest[col] > 0){

			if(next_rest[col] >= 3)continue;

			if(ADJ[row][col][Under].size() == 0){ //下に伸ばす相手なし

				continue;
			}

			int next_row = ADJ[row][col][Under][0].row;
			if(next_rest[col] > table[next_row][col]-'0'){ //下に伸ばす相手の最大容量を超過

				continue;
			}
		}

		ret += recursive(row,col+1,next_rest,to_r);
		ret %= MOD;
	}

	return dp[row][col][tmp_code] = ret;
}


int main(){

	POW[0] = 1;
	for(int i = 1; i < SIZE; i++){

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

	scanf("%d %d",&H,&W);

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

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

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] == '.')continue;

			//右
			for(int k = col+1; k < W; k++){
				if(table[row][k] != '.'){
					ADJ[row][col][Right].push_back(LOC(row,k));
					break;
				}
			}
			//下
			for(int k = row+1; k < H; k++){
				if(table[k][col] != '.'){
					ADJ[row][col][Under].push_back(LOC(k,col));
					break;
				}
			}
		}
	}

	for(int row = 0; row <= H; row++){
		for(int col = 0; col <= W; col++){
			for(int state = 0; state < POW[W+2]; state++){

				dp[row][col][state] = -1;
			}
		}
	}

	ll first_rest[SIZE];
	for(int col = 0; col < W; col++){

		if(table[0][col] == '.'){

			first_rest[col] = 0;

		}else{

			first_rest[col] = table[0][col]-'0';
		}
	}

	printf("%lld\n",recursive(0,0,first_rest,0));

	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 201164
final_rank: 10

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


#define MOD 100000007
#define SIZE 12

enum Type{
	Right,
	Under,
};

struct LOC{
	LOC(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

int H,W;
char table[SIZE][SIZE];
ll POW[SIZE];
vector<LOC> ADJ[SIZE][SIZE][2];
ll dp[SIZE][SIZE][177147];



ll makeCode(ll rest[SIZE],ll to_right){

	ll ret = to_right+POW[W];
	for(int col = 0; col < W; col++){

		ret += POW[col]*rest[col];
	}

	return ret;
}


/*void print_rest(ll rest[SIZE]){

	for(int col = 0; col < W; col++){

		printf("rest[%d]:%lld\n",col,rest[col]);
	}
}*/


//dp[行][列][状態] := 場合の数

ll recursive(int row,int col,ll rest[SIZE],ll to_right){

	/*printf("row:%d col:%d\n",row,col);
	print_rest(rest);*/

	ll tmp_code = makeCode(rest,to_right);
	if(dp[row][col][tmp_code] != -1){

		return dp[row][col][tmp_code];
	}

	ll next_rest[SIZE];

	if(col == W){

		if(row == H-1){

			bool FLG = true;
			for(int i = 0; i < W; i++){
				if(rest[i] > 0){

					FLG = false;
					break;
				}
			}

			if(FLG){

				return 1;

			}else{

				return 0;
			}

		}else{ //次の行の準備

			for(int i = 0; i < W; i++){
				if(table[row+1][i] == '.'){

					next_rest[i] = rest[i];

				}else{

					next_rest[i] = (table[row+1][i]-'0')-rest[i];
				}
			}

			return dp[row][col][tmp_code] = recursive(row+1,0,next_rest,0);
		}
	}

	if(table[row][col] == '.'){

		return dp[row][col][tmp_code] = recursive(row,col+1,rest,to_right);
	}

	if(rest[col] >= 5){

		return dp[row][col][tmp_code] = 0;
	}

	ll ret = 0;

	int next_col;
	bool right_FLG = true;

	if(ADJ[row][col][Right].size() == 0){ //右に相手なし

		//printf("右に相手なし\n");

		right_FLG = false;

	}else{ //右に相手あり

		next_col = ADJ[row][col][Right][0].col;
		for(int k = col+1; k <= next_col-1; k++){ //この区間は全て"."であるはず
			if(rest[k] > 0){ //★線分の交差が起きるので不可★

				//printf("交差\n");
				right_FLG = false;
				break;
			}
		}
	}

	if(!right_FLG && rest[col] > 0){ //右に線分を伸ばせない,かつ残量あり

		if(rest[col] >= 3){

			return dp[row][col][tmp_code] = 0;
		}

		if(ADJ[row][col][Under].size() == 0){ //下に伸ばす相手なし

			return dp[row][col][tmp_code] = 0;
		}

		int next_row = ADJ[row][col][Under][0].row;
		if(rest[col] > table[next_row][col]-'0'){ //下に伸ばす相手の最大容量を超過

			return dp[row][col][tmp_code] = 0;
		}
	}


	ll maximum = min(rest[col],2LL);
	if(!right_FLG){

		maximum = 0;
	}

	//printf("maximum:%lld\n",maximum);

	for(ll to_r = 0; to_r <= maximum; to_r++){ //右に伸ばす数の走査


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

			next_rest[i] = rest[i];
		}

		if(to_r == 0){

			//Do nothing

		}else{ //交差しない、かつ相手あり

			if(to_r > rest[next_col])break;

			next_rest[col] = rest[col]-to_r;
			next_rest[next_col] = rest[next_col]-to_r;
		}


		if(next_rest[col] > 0){

			if(next_rest[col] >= 3)continue;

			if(ADJ[row][col][Under].size() == 0){ //下に伸ばす相手なし

				continue;
			}

			int next_row = ADJ[row][col][Under][0].row;
			if(next_rest[col] > table[next_row][col]-'0'){ //下に伸ばす相手の最大容量を超過

				continue;
			}
		}

		ret += recursive(row,col+1,next_rest,to_r);
		ret %= MOD;
	}

	return dp[row][col][tmp_code] = ret;
}


int main(){

	POW[0] = 1;
	for(int i = 1; i < SIZE; i++){

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

	scanf("%d %d",&H,&W);

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

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

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] == '.')continue;

			//右
			for(int k = col+1; k < W; k++){
				if(table[row][k] != '.'){
					ADJ[row][col][Right].push_back(LOC(row,k));
					break;
				}
			}
			//下
			for(int k = row+1; k < H; k++){
				if(table[k][col] != '.'){
					ADJ[row][col][Under].push_back(LOC(k,col));
					break;
				}
			}
		}
	}

	for(int row = 0; row <= H; row++){
		for(int col = 0; col <= W; col++){
			for(int state = 0; state < POW[W+1]; state++){

				dp[row][col][state] = -1;
			}
		}
	}

	ll first_rest[SIZE];
	for(int col = 0; col < W; col++){

		if(table[0][col] == '.'){

			first_rest[col] = 0;

		}else{

			first_rest[col] = table[0][col]-'0';
		}
	}

	printf("%lld\n",recursive(0,0,first_rest,0));

	return 0;
}
accuracy: 0.4666666666666667
time_ms: 90
memory_kb: 170704
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
Int h,w;
string s[100];
const Int MOD = 1e8+7;
Int dp[11][100000];
Int po[20];
Int dfs(Int y,Int b);
Int dfs2(Int y,Int x,vector<Int> &v);

const Int DBG = 0;
Int dfs(Int y,Int b){
  if(DBG) cout<<y<<":"<<b<<endl;
  if(y==h) return b==0;
  Int &res=dp[y][b];
  if(~res) return res;
  res=0;
  vector<Int> v(w,0);
  for(Int i=0;i<w;i++){
    v[i]=-((b/po[i])%3);
    if(s[y][i]=='.') continue;
    v[i]+=s[y][i]-'0';
    if(v[i]<0) return res;
  }
  if(DBG){
    for(Int i=0;i<w;i++) cout<<v[i]<<":";
    cout<<endl;
  }
  res+=dfs2(y,0,v);
  res%=MOD;
  if(DBG) cout<<y<<":"<<b<<":"<<res<<endl;
  return res;
}
Int calc(vector<Int> &v){
  Int b=0;
  for(Int i=w-1;i>=0;i--){
    if(v[i]>0||-v[i]>2) return -1;
    b=b*3+(-v[i]);
  }
  return b;
}
Int dfs2(Int y,Int x,vector<Int> &v){
  //cout<<y<<"*"<<x<<endl;
  while(x<w&&!isdigit(s[y][x])) x++;
  if(x==w){
    Int b=calc(v);
    if(~b) return dfs(y+1,b);
    return 0;
  }
  Int px=x++,flg=0;
  while(x<w&&!isdigit(s[y][x])){
    flg|=(v[x]<0); 
    x++;
  }
  if(x==w){
    v[px]*=-1;
    Int res=dfs2(y,x,v);
    v[px]*=-1;
    return res;
  }
  Int res=0;
  Int pv=v[px];
  for(Int i=0;i<=pv;i++){
    if(i>=3||pv-i>=3) continue;
    if(flg && i!=pv) continue;
    v[x]-=pv-i;
    v[px]=-i;
    res+=dfs2(y,x,v);
    res%=MOD;
    v[x]+=pv-i;
    v[px]=pv;
  }
  return res;
}


signed main(){  
  cin.tie(0);
  ios::sync_with_stdio(0);
  cin>>h>>w;
  for(Int i=0;i<h;i++) cin>>s[i];
  po[0]=1;
  for(Int i=1;i<20;i++) po[i]=po[i-1]*3;
  memset(dp,-1,sizeof(dp));
  cout<<dfs(0,0)<<endl;
  return 0;
}
accuracy: 1
time_ms: 1420
memory_kb: 11784
final_rank: 6

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


const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 10;
	id += y;
	for (int i = 0; i < v.size(); ++i) {
		assert(v[i] >= 0 && v[i] <= 2);
		id *= 31;
		id += v[i];
	}
	id *= 31;
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	assert(x < C);
	assert(R != y || !x);
	const  long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 700
memory_kb: 94932
final_rank: 16

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


const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 15;
	id += y;
	for (int i = 0; i < v.size(); ++i) {
		assert(v[i] >= 0 && v[i] <= 2);
		id *= 31;
		id += v[i];
	}
	id *= 31;
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	assert(x < C);
	assert(R != y || !x);
	const  long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1190
memory_kb: 118896
final_rank: 7

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


const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


int getid(int x, int y, const vector<int>&v, int l) {
	 int id = 0;
	id += x;
	id *= 15;
	id += y;
	for (int i = 0; i < v.size(); ++i) {
		assert(v[i] >= 0 && v[i] <= 2);
		id *= 31;
		id += v[i];
	}
	id *= 31;
	id += l;
	return id;
}
map< int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	assert(x < C);
	assert(R != y || !x);
	const  int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 980
memory_kb: 72524
final_rank: 13

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


const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


int getid(int x, int y, const vector<int>&v, int l) {
	 int id = 0;
	id += x;
	id *= 10;
	id += y;
	for (int i = 0; i < v.size(); ++i) {
		assert(v[i] >= 0 && v[i] <= 2);
		id *= 3;
		id += v[i];
	}
	id *= 3;
	id += l;
	return id;
}
map< int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	assert(x < C);
	assert(R != y || !x);
	const  int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 680
memory_kb: 71904
final_rank: 12

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


const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 10;
	id += y;
	for (int i = 0; i < v.size(); ++i) {
		assert(v[i] >= 0 && v[i] <= 2);
		id *= 3;
		id += v[i];
	}
	id *= 3;
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	assert(x < C);
	assert(R != y || !x);
	const long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 720
memory_kb: 94820
final_rank: 19

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


const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 10;
	id += y;
	id *= 10;
	for (int i = 0; i < v.size(); ++i) {
		assert(v[i] >= 0 && v[i] <= 2);
		id += v[i];
		id *= 10;
	}
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	assert(x < C);
	assert(R != y || !x);
	const long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 710
memory_kb: 94740
final_rank: 17

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



const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 10;
	id += y;
	id *= 10;
	for (int i = 0; i < v.size(); ++i) {
		id += v[i];
		id *= 10;
	}
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	//assert(x < C);
	assert(R != y || !x);
	const long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 700
memory_kb: 94864
final_rank: 15

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



const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 10;
	id += y;
	id *= 10;
	for (int i = 0; i < v.size(); ++i) {
		id += v[i];
		id *= 10;
	}
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	//assert(x < C);
	//assert(R != y || x);
	const long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
		}
	}
	assert(false);
	return memo[id];
}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 710
memory_kb: 94788
final_rank: 18

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



const int mod = 100000007;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const long long  int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}


long long int getid(int x, int y, const vector<int>&v, int l) {
	long long int id = 0;
	id += x;
	id *= 10;
	id += y;
	id *= 10;
	for (int i = 0; i < v.size(); ++i) {
		id += v[i];
		id *= 10;
	}
	id += l;
	return id;
}
map<long long int, Mod>memo;
int R, C;
vector<vector<int>>field;
Mod getans(int x, int y, const vector<int>&v,int l) {
	//assert(x < C);
	//assert(R != y || x);
	const long long int id = getid(x, y, v, l);
	if (memo.find(id) != memo.end()) {
		return memo[id];
	}
	else {
		if (y == R) {
			bool ok = true;
			if (l)ok = false;
			if (!all_of(v.begin(), v.end(), [](const int n) {return n == 0; }))ok = false;
			return memo[id] = ok;
		}
		else {
			if (x == 0) {
				if (l)return memo[id] = 0;
			}
			if (field[y][x]) {
				Mod ans = 0;
				for (int lnum = 0; lnum <= 2;lnum++) {
					int dnum = field[y][x] - l - v[x]-lnum;
					if (dnum < 0 || dnum>= 3)ans += 0;
					else {
						int nexty = y, nextx = x + 1;
						vector<int>nextv(v);
						if (nextx == C) {
							nextx = 0;
							nexty++;
						}
						nextv[x] = dnum;
						ans += getans(nextx, nexty, nextv, lnum);
					}
				}
				return memo[id] = ans;
			}
			else {
				if (l&&v[x])return memo[id] = 0;
				else {
					int nexty = y, nextx = x + 1;
					vector<int>nextv(v);
					if (nextx == C) {
						nextx = 0;
						nexty++;
					}
					return memo[id]=getans(nextx, nexty,v, l);
				}
			}
			
		}
	}

}
int main() {
	cin >> R >> C;
	field = vector<vector<int>>(R, vector<int>(C));
	for (int i = 0; i < R; ++i) {
		string st; cin >> st;
		for (int j = 0; j < C; ++j) {
			if (st[j] == '.')field[i][j] = 0;
			else field[i][j] = st[j] - '0';
		}
	}
	vector<int>v(C);
	Mod ans = getans(0, 0, v, 0);
	cout << ans << endl;
	return 0;
}
accuracy: 0.43333333333333335
time_ms: 700
memory_kb: 94852
final_rank: 14

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<algorithm>	
#include<map>
#include<set>
#include<utility>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<cstdio>
#include<sstream>
#include<iomanip>
#define loop(i,a,b) for(int i=a;i<b;i++) 
#define rep(i,a) loop(i,0,a)
#define pb push_back
#define mp make_pair
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
using namespace std;
//kaewasuretyuui
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef pair<int,pii> pip;
typedef vector<pip>vip;
const double PI=acos(-1);
const double EPS=1e-8;
const double inf=1e8;
vector<map<vi,int> >dp;
vi tmp;
string tms;
int r,n,m,c,MOD=100000007;
//map<vi,int>q;
vi q;
vi f(int a){
	vi out(m);
	rep(i,m){
		out[m-i-1]=a%3;
		a/=3;
	}
	return out;
}
int ff(vi a){
	int t=0;
	rep(i,m){
		t*=3;
		t+=a[i];
	}
	return t;
}
void dfs(int a){
	if(a==m){
		if(r)return;
		(q[ff(tmp)]+=c)%=MOD;	
		return;
	}
	if(tms[a]=='.'){
		if(r&&tmp[a])return;
		dfs(a+1);
		return;
	}
	int w=r;
	if(tms[a]-'0'<w)return;
	tms[a]-=w;
	rep(i,min(3,tms[a]-'0'+1))if(tms[a]-'0'-i<3){
		tmp[a]=i;
		r=tms[a]-'0'-i;
		dfs(a+1);
		tmp[a]=0;
	}
	
	tms[a]+=w;
}
int main(){
	cin>>n>>m;
	vs in(n);
	rep(i,n)cin>>in[i];
//	map<vi,int>dp;
	int N=pow(3,m);
	vi dp(N);
	dp[0]=1;
	rep(i,n){
		q=vi(N);
		rep(z,N)if(dp[z]){
	//		for(map<vi,int>::iterator it=dp.begin();it!=dp.end();it++){
			tmp=f(z);
			tms=in[i];
			bool h=true;
			rep(j,m)if(tms[j]!='.'){
				if(tmp[j]>tms[j]-'0')h=false;
				else{
					tms[j]-=tmp[j];
					tmp[j]=0;
				}
			}
			if(!h)continue;
			r=0;
			c=dp[z];
			dfs(0);
		}
		dp=q;
	}
	cout<<dp[0]<<endl;
}
accuracy: 1
time_ms: 3010
memory_kb: 3824
final_rank: 8

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

int W, H, a[11][11], rt[10][10], dn[10][10], dp[2][1 << 20], y, z;
vector<int> b;

void f(int x, int p) {
    int rx = rt[y][x];
    int mn = min({ 2, a[y][x], a[y][rx] });
    mn = p >> x * 2 + 2 & ~(-1 << (rx - x - 1) * 2) ? 0 : mn;
    for (int i = a[y][x] - min({ 2, a[y][x], a[dn[y][x]][x] }); i <= mn; ++i) {
        int q = p & ~(3 << x * 2) | a[y][x] - i << x * 2;
        if (rx == W) {
            dp[y & 1][q] = (dp[y & 1][q] + z) % 100000007;
        } else {
            a[y][rx] -= i;
            f(rx, q);
            a[y][rx] += i;
        }
    }
}

void g(int x, int p) {
    if (x) {
        for (int i = 0; i < 3; ++i)
            g(x - 1, p << 2 | i);
    } else {
        b.emplace_back(p);
    }
}

int main() {
    cin >> H >> W;
    int A[11][11]{};
    for (int y = 0; y < H; ++y) {
        char s[11];
        cin >> s;
        bool none = true;
        for (int x = 0; x < W; ++x) {
            if (s[x] != '.') {
                A[y][x] = s[x] - '0';
                none = false;
            }
        }
        if (none) {
            --H;
            --y;
        }
    }
    for (int y = 0; y < H; ++y) {
        for (int x = 0; x < W; ++x) {
            if (A[y][x]) {
                int i = x + 1;
                for (; i < W && !A[y][i]; ++i);
                rt[y][x] = i;
                for (i = y + 1; i < H && !A[i][x]; ++i);
                dn[y][x] = i;
            }
        }
    }
    memcpy(a, A, sizeof a);
    g(W, 0);
    dp[1][0] = 1;
    for (y = 0; y < H; ++y) {
        memset(dp[y & 1], 0, sizeof dp[y & 1]);
        int x = 0;
        for (; !a[y][x]; ++x);
        for (int p : b) {
            z = dp[y + 1 & 1][p];
            if (z) {
                for (int i = x; i < W; i = rt[y][i])
                    a[y][i] -= p >> i * 2 & 3;
                f(x, p);
                memcpy(a[y], A[y], sizeof a[y]);
            }
        }
    }
    cout << dp[H + 1 & 1][0] << endl;
    return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11508
final_rank: 4

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

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

using namespace std;

const int mod = 100000007;
int h,w,pow3[13];
int dp[11*11][180000];
char field[12][12];

#define get(bit,x) ((bit)/pow3[(x)]%3)
#define set(bit,x,value) ((bit)-(((bit)/pow3[x]%3)*pow3[x])+(value*pow3[x]))
#define fix(bit,width) ((bit)*3%pow3[width])

void compute(){
  bool starter = true;  
  rep(y,h){
    rep(x,w){
      if( starter && field[y][x] == '.' ) continue;
      if( starter ) { starter = false; ++dp[x+y*w][0]; }

      bool update = false;
      rep(bitmask3,pow3[w+1]){
	if( dp[x+y*w][bitmask3] == 0 ) continue;
	update = true;
	int left = get(bitmask3,x);
	int top  = get(bitmask3,x+1);
	if( field[y][x] == '.' ) {
	  if( left && top ) continue;
	  if( left && x == w-1 ) continue;
	  if( top && y == h-1 ) continue;
	  int nbitmask = bitmask3;
	  nbitmask = set(nbitmask,x,top);
	  nbitmask = set(nbitmask,x+1,left);
	  if( x == w-1 ) nbitmask = fix(nbitmask,w+1);
	  ( dp[x+y*w+1][nbitmask] += dp[x+y*w][bitmask3] ) %= mod;
	  continue;
	}

	int remain = field[y][x] - '0' - left - top;
	if( remain < 0 || remain > 4 ) continue;
	rep(next_bottom,3){
	  int next_right = remain - next_bottom;
	  if( next_right < 0 || next_right > 2 ) continue;
	  int nbitmask = bitmask3;
	  if( next_right && x == w-1 ) continue;
	  if( next_bottom && y == h-1 ) continue;
	  nbitmask = set(nbitmask,x,next_bottom);
	  nbitmask = set(nbitmask,x+1,next_right);
	  if( x == w-1 ) nbitmask = fix(nbitmask,w+1);
	  ( dp[x+y*w+1][nbitmask] += dp[x+y*w][bitmask3] ) %= mod;
	}
      }
    }
  }
  int sum = 0;
  rep(i,pow3[w+1]) ( sum += dp[h*w][i] ) %= mod;
  assert( sum >= 0 );
  cout << sum << endl;
}

int main(){
  pow3[0] = 1;
  REP(i,1,13) pow3[i] = pow3[i-1] * 3;

  cin >> h >> w;
  rep(i,h) scanf(" %s",&field[i]);
  compute();
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 70832
final_rank: 2

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
char str[20][20];
int pow3[13];
int mod=100000007;
int dp[12][12][60000][3];
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%s",str[i]);
	}
	pow3[0]=1;
	for(int i=1;i<13;i++)pow3[i]=pow3[i-1]*3;
	dp[0][0][0][0]=1;
	for(int i=0;i<a;i++){
		for(int j=0;j<b;j++){
			for(int k=0;k<pow3[b];k++){
				for(int l=0;l<3;l++){
					if(!dp[i][j][k][l])continue;
			//		printf("%d %d %d %d: %d\n",i,j,k,l,dp[i][j][k][l]);
					if(str[i][j]=='.'){
						if(k%3&&l)continue;
						dp[i][j+1][k/3+pow3[b-1]*(k%3)][l]=(dp[i][j+1][k/3+pow3[b-1]*(k%3)][l]+dp[i][j][k][l])%mod;
					}else{
						int rem=str[i][j]-'0'-l-k%3;
						if(rem<0)continue;
						for(int m=0;m<3;m++)for(int n=0;n<3;n++){
							if(rem==m+n){
								dp[i][j+1][k/3+pow3[b-1]*m][n]=(dp[i][j+1][k/3+pow3[b-1]*m][n]+dp[i][j][k][l])%mod;
							}
						}
					}
				}
			}
		}
		for(int j=0;j<pow3[b];j++){
			dp[i+1][0][j][0]=dp[i][b][j][0];
		}
	}
	printf("%d\n",dp[a][0][0][0]);
}
accuracy: 1
time_ms: 50
memory_kb: 85032
final_rank: 5