E. Omkar and Forest
题意:
给n*m的字符矩阵,有0和#两种,你可以把#改成任意非负整数,满足以下两种条件,
1.这个单元格中的数于其相邻的单元格差的绝对值小于等于1。
2.这个单元格的数如果大于0,则其必须严格大于其相邻的至少一个单元格的数。
问有多少种构造方案。
感觉cf题目最近的标的分数有点偏高,这个题感觉1900左右吧。
思路:
首先猜了个结论,就是一个格子的值一定为它到理它最近的0的曼哈顿距离x。
首先很明显它不可能大于x,大于x明显明显不合法。
然后证明它不可能小于x,如果这个值小于x,那么它周围一定有一个数比它小1,然后移动到这个数上再找,则可以在小于x的曼哈顿距离内找到0,与假设出现冲突,所以这个值不能小于x。
综合得这个值一定为x。
也就是说只要这个矩阵中所有的0确定了,其他的值也就确定了,所以#只有两种可能0或者已经确定的值,这样总方案数就是2的(#的数目)次方。
样例也挺良心,明显这个矩阵要有至少一个0,所以如果整个矩阵全是#就得特判减1。
感觉要是没这个样例可能得卡掉很多人。
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX_N=2010;
const long long MOD=1e9+7;
long long pow_mod(long long a,long long n,long long m){
long long res=1;
while(n){
if(n&1)
res=res*a%m;
a=a*a%m;
n>>=1;
}
return res;
}
char s[MAX_N];
int main(void){
int T,n,m,i,j;
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
int num=0;
for(i=1;i<=n;i++){
scanf("%s",s+1);
for(j=1;j<=m;j++){
if(s[j]=='0')
num++;
}
}
long long ans=pow_mod(2,n*m-num,MOD);
if(num==0)
ans=(ans-1+MOD)%MOD;
printf("%lld\n",ans);
}
return 0;
}