计数
一道观察性质好题- -。
一个朴素的做法是插头DP,然而这题数据范围太大,考虑题目性质。
来个例子”L12”,其中12表示还没有填,L表示这个位置放了一个L形的管道。仔细观察可知此时1必有左插头,2不能有左插头因此必有右插头。类似地我们可以完全把一整行的左右插头确定下来。
确定完之后我们可以保证这一行不会在左右插头的位置发生泄漏。同理做一下上下。最后答案就是2^(没确定的行和列)
#include<cstdio>
#include<cstring>
#define N 500005
#define MOD 1000003
using namespace std;
namespace runzhe2000
{
typedef long long ll;
int n, m, r[N], c[N], fac;
int getc()
{
char c = getchar();
for(; (c < '1' || c > '4') && c != '.'; c = getchar());
return c == '.' ? 0 : c - '0';
}
void main()
{
scanf("%d%d",&n,&m);
memset(r,-1,sizeof(r));
memset(c,-1,sizeof(c));
for(int i = 1, v, rr, cc; i <= n; i++)
for(int j = 1; j <= m; j++)
{
if((v = getc()))
{
if(v == 1){rr = j&1; cc = i&1;}
if(v == 2){rr = j&1; cc = (~i)&1;}
if(v == 3){rr = (~j)&1; cc = (~i)&1;}
if(v == 4){rr = (~j)&1; cc = i&1;}
if(r[i] == (rr^1)) {puts("0");return;}
if(c[j] == (cc^1)) {puts("0");return;}
r[i] = rr; c[j] = cc;
}
}
for(int i = 1; i <= n; i++) if(r[i] == -1) fac++;
for(int j = 1; j <= m; j++) if(c[j] == -1) fac++;
int ans = 1, base = 2;
for(; fac; fac >>= 1)
{
if(fac & 1) ans = (ll)ans * base % MOD;
base = (ll)base * base % MOD;
}
printf("%d\n",ans);
}
}
int main()
{
runzhe2000::main();
}