列表

详情


NC21346. 网格填数

描述

有一个的网格,第行第列的元素记为,上面填满了数字,但是由于某些原因,有些数字缺失了
已知网格本来是满足如下的性质的
1:对于所有满足条件的
是个奇数
2: 对于所有满足条件的
是个奇数
现在给你缺失数据的网格以及,你需要将缺失的地方填成数字,请问有多少种填法可以满足网格本来的性质
输出方案数对取模

输入描述

第一行输入
接下来行每行输入个字符,缺失的位置用'.'表示

输出描述

输出一个整数

示例1

输入:

2 2 2 2 
12
2.

输出:

5

示例2

输入:

2 2 2 2
21
1.

输出:

4

示例3

输入:

3 3 1 1
...
...
...

输出:

1953125

示例4

输入:

2 6 2 3
..58..
..47..

输出:

0

示例5

输入:

4 8 4 4
...1.2.3
4.5.6...
...7.8.9
1.2.3...

输出:

886073030

示例6

输入:

20 20 10 10
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................
....................

输出:

240076532

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 18ms, 内存消耗: 632K, 提交时间: 2023-05-31 15:09:04

#include <bits/stdc++.h>

#define ll long long 
#define int ll

using namespace std;

const int N = 20, M = (1 << 20), T = 60;
const int mod = 1e9 + 7;
int h, w, n, m;
char s[T];
int dp[N][M];   // 当第i行所有数状态为j时  0 1 0 1 0 0 
int d1[N][N];   // 当ij为奇数时候有多少种选择方案
int d2[N][N];
bool h1[N][N],h2[N][N];

signed main()
{
	scanf("%lld%lld%lld%lld", &h, &w, &n, &m);
	for(int i = 0; i < n; i ++ ) 
		for(int j = 0; j < m; j ++ ) d1[i][j] = d2[i][j] = 1;
	
	for(int i = 0; i < h; i ++ ) {
		scanf("%s", s);
		for(int j = 0; j < w; j ++ ) {
			if(s[j] == '.') {
				d1[i % n][j % m] = d1[i % n][j % m] * 5 % mod;
				d2[i % n][j % m] = d2[i % n][j % m] * 4 % mod;
			}
			else if((s[j] - '0') % 2) h1[i % n][j % m] = true;
			else h2[i % n][j % m] = true;
		}
	}
	
	for(int i = 0; i < n; i ++ )
		for(int j = 0; j < m; j ++ ) {
		if(h1[i][j] && h2[i][j]) {
			puts("0");
			return 0;
		}
	}
	dp[0][0] = 1;
	for(int i = 1; i <= n; i ++ ) {
		for(int j = 0; j <= (1 << m) - 1; j ++ ) {
			int sum = 1, tag = 0;
			bool flag = false;
			for(int k = 0; k < m; k ++ ) {
				if(j & (1 << k)) {  // 奇数
					tag ++ ;
					sum = sum * d1[i - 1][k] % mod;
					if(h2[i - 1][k]) {
						flag = true;
						break;
					}
				}
				else {   // 偶数
					sum = sum * d2[i - 1][k] % mod;
					if(h1[i - 1][k]) {
						flag = true;
						break;
					}
				}
			}
			
			if(flag || tag % 2 == 0) continue;
			for(int l = 0; l <= (1 << m) - 1; l ++ ) {
				dp[i][l ^ j] = (dp[i][l ^ j] + dp[i - 1][l] * sum) % mod;
			}
		}
	}
	
	printf("%lld\n", dp[n][(1 << m) - 1]);
	return 0;
}

C++ 解法, 执行用时: 48ms, 内存消耗: 820K, 提交时间: 2021-08-21 14:36:23

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char st[100][100];
ll a[20][20],b[20][20],dp[20][1<<11],mod=1e9+7;
bool aa[20][20],bb[20][20];
int main() {
	int h,w,n,m,i,j,k,p;
	cin>>h>>w>>n>>m;
	char s[100];
	for(i=0;i<n;i++){
		for(j=0;j<m;j++)
		a[i][j]=b[i][j]=1; 
	}
	for(i=0;i<h;i++){
		scanf("%s",s);
		for(j=0;j<w;j++){
			if(s[j]=='.'){
				a[i%n][j%m]=a[i%n][j%m]*5%mod;
				b[i%n][j%m]=b[i%n][j%m]*4%mod;
			}
			else if((s[j]-'0')%2)
			aa[i%n][j%m]=1;
			else
			bb[i%n][j%m]=1;
		}
	}
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			if(aa[i][j]&&bb[i][j]){
			puts("0");
			return 0;	
			}
		}
	}
	dp[0][0]=1;
	for(i=1;i<=n;i++){
		for(j=0;j<(1<<m);j++){
			ll sum=1,tag=0,f=0;
			for(k=0;k<m;k++){
				if((1<<k)&j){
					tag^=1;
					if(bb[i-1][k]){
					f=1;
					break;	
					}
					sum=(sum*a[i-1][k])%mod;
				}
				else{
					if(aa[i-1][k]){
					f=1;
					break;	
					}
					sum=(sum*b[i-1][k])%mod;
				}	
			}
			if(f==1||tag==0)
			continue;
				for(p=0;p<(1<<m);p++)
					dp[i][j^p]=(dp[i][j^p]+sum*dp[i-1][p])%mod;	
		}
	}
	cout<<dp[n][(1<<m)-1];
  return 0;
}

上一题