2017 Multi-University Training Contest - Team 7:1003. Color the chessboard(...)

其他题目题解:

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;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值