[CF1536E] Omkar and Forest

前言

结论题?结论题!

题目

CF

洛谷

题目大意:

\(t\) 组数据,给一个 \(n\)\(m\) 列的网格,每个点要么是 0 要么是 # 。如果是 0 ,那么这个位置就是数字 \(0\),否则可以是任意非负整数。我们认为网格是好的,需要满足以下两个条件:

  • 对于每两个相邻的格子,其中的数字之差的绝对值不超过 \(1\)
  • 如果一个格子里面是正整数,那么与它相邻的格子中必须有一个数字严格小于它。

询问有多少个合法的网格,对 \(10^9+7\) 取模。

\(1\le t\le 100;1\le n,m\le 2000;\sum n,\sum m\le 2000;nm\ge 2;\)

讲解

其实当你读完两个条件的时候就应该醒悟过来:这不就是 BFS 的过程吗?!

所以很显然,如果我们确定了初始的 \(0\) 的位置,那么整张图就确定了!

所以答案就是 \(2^{cnt}\),其中 \(cnt\)# 的个数。

就这样?

然后发现过不了样例,发现有种情况没有考虑:

如果全是 #,我们把全 \(1\) 的情况考虑进去了!

所以减一即可。

代码

//12252024832524
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std;

typedef long long LL;
const int MAXN = 2005;
const int MOD = 1e9 + 7;
int n,m;
char a[MAXN][MAXN];

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

int qpow(int x,int y)
{
	int ret = 1;
	while(y){if(y & 1) ret = 1ll * ret * x % MOD;x = 1ll * x * x % MOD;y >>= 1;}
	return ret;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);

	for(int T = Read(); T ;-- T)
	{
		n = Read(); m = Read(); int ans = 0;
		for(int i = 1;i <= n;++ i) scanf("%s",a[i]+1);
		for(int i = 1;i <= n;++ i)
			for(int j = 1;j <= m;++ j)
				if(a[i][j] == '#') ans++;
		if(ans == 1) Put(2,'\n');
		else if(ans == n*m) Put(qpow(2,ans)-1,'\n');
		else Put(qpow(2,ans),'\n');
	}
	return 0;
}
posted @ 2021-06-12 18:56  皮皮刘  阅读(76)  评论(0编辑  收藏  举报