其他题目题解:
2017 Multi-University Training Contest - Team 7:1005. Euler theorem
2017 Multi-University Training Contest - Team 7:1011. Kolakoski
2017 Multi-University Training Contest - Team 7:1008. Hard challenge
2017 Multi-University Training Contest - Team 7:1002. Build a tree
2017 Multi-University Training Contest - Team 7:1010. Just do it
题意:有一个n*m棋盘,每个格子都有一种颜色,红色蓝色或白色,你要将所有的白色棋子染成另外两种颜色,求有多少种染色方案使得最后所有长和宽都为偶数的子棋盘红色格子和蓝色格子数量都相等
其实只要满足所有2*2的子棋盘红色格子数量和蓝色格子数量都为2就好了
将所有行+列为偶数的格子反色(蓝变红,红变蓝)那么新的棋盘如果合法,就必须满足所有的列要不全蓝要不全红,或者所有的行要不全蓝要不全红
这样问题就简单了,反色之后
遍历一次所有的行,看是否有一行上既有蓝色又有红色,如果有,就停止检测,直接遍历列
否则计算有多少行全是白色的,答案加上2^x,x为行数
然后遍历一次所有的列,看是否有一列上既有蓝色又有红色,如果有,就结束,
否则计算有多少列全是白色的,答案再加上2^x,x为列数
注意如果可以全红或全蓝那么会被算上两次,记得去重
#include<stdio.h>
#define LL long long
#define mod 998244353
char str[1005];
LL a[1005][1005], er[1005] = {1,2};
int main(void)
{
LL T, n, m, i, j, p, q, B, R, yb, yr;
for(i=2;i<=1000;i++)
er[i] = er[i-1]*2%mod;
scanf("%lld", &T);
while(T--)
{
scanf("%lld%lld", &n, &m);
p = q = 0, yb = yr = 1;
for(i=1;i<=n;i++)
{
scanf("%s", str+1);
for(j=1;j<=m;j++)
{
if(str[j]=='R') a[i][j] = 1;
else if(str[j]=='B') a[i][j] = 0;
else a[i][j] = -1;
if((i+j)%2 && a[i][j]!=-1)
a[i][j] ^= 1;
}
}
for(i=1;i<=n;i++)
{
R = B = 0;
for(j=1;j<=m;j++)
{
if(a[i][j]==1)
R = 1, yb = 0;
else if(a[i][j]==0)
B = 1, yr = 0;
}
if(R==B && B==0)
p++;
else if(R==B && B==1)
{
p = -1;
break;
}
}
for(j=1;j<=m;j++)
{
R = B = 0;
for(i=1;i<=n;i++)
{
if(a[i][j]==1)
R = 1;
else if(a[i][j]==0)
B = 1;
}
if(R==B && B==0)
q++;
else if(R==B && B==1)
{
q = -1;
break;
}
}
if(p==-1 && q==-1)
printf("0\n");
else if(p!=-1 && q==-1)
printf("%lld\n", er[p]);
else if(p==-1 && q!=-1)
printf("%lld\n", er[q]);
else
printf("%lld\n", (er[p]+er[q]-yb-yr+mod)%mod);
}
return 0;
}