hdu-6122 Color the chessboard 思维

55 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=6122

 

有一个nnnmmm列的棋盘,最初每个位置是指定的红色或蓝色或白色。你要将白色的位置染成红色或蓝色,使得对于任意一个长宽均为偶数的连续子棋盘,其中红色和蓝色的位置数相等,求方案数模9982443539982443539982443531≤n,m≤1031\leq n,m\leq10^31n,m103

即每个2*2连续子矩阵红蓝数量相等。令红为1,蓝为0,如果让把所有格子按行号与列号的和奇偶反色,则转化为每个2*2子矩阵对角线的和相等。发现这个条件当且仅当每行都是全1或全0,或者每列都是全1或全0,讨论一下就好了。

(自http://bestcoder.hdu.edu.cn/blog/

  需要特殊注意下每行全涂黑和每列全涂黑是一样的,白也是

#include<bits/stdc++.h>
using namespace std;
const int mo=998244353;
char ch[1005][1005];
int a1[1005],b1[1005];
char a2[1005],b2[1005];
int main()
{
    int T,i,j,n,m;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        for(i=1;i<=n;i++)
            scanf("%s",ch[i]+1);
        
        for(i=1;i<=n;i++)
            a1[i]=2,a2[i]='?';
        for(i=1;i<=m;i++)
            b1[i]=2,b2[i]='?';
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if((i+j)&1)
                {
                    if(ch[i][j]=='R')
                        ch[i][j]='B';
                    else if(ch[i][j]=='B')
                        ch[i][j]='R';
                }
                if(ch[i][j]=='R')
                {
                    if(a1[i])
                    {
                        if(a2[i]=='?')
                        a2[i]='R',a1[i]=1;
                        else if(a2[i]=='B')
                        a1[i]=0;
                    }
                    if(b1[j])
                    {
                        if(b2[j]=='?')
                        b2[j]='R',b1[j]=1;
                        else if(b2[j]=='B')
                        b1[j]=0;
                    }
                }
                else if(ch[i][j]=='B')
                {
                    if(a1[i])
                    {
                        if(a2[i]=='?')
                        a2[i]='B',a1[i]=1;
                        else if(a2[i]=='R')
                        a1[i]=0;
                    }
                    if(b1[j])
                    {
                        if(b2[j]=='?')
                        b2[j]='B',b1[j]=1;
                        else if(b2[j]=='R')
                        b1[j]=0;
                    }
                }
            }
        }
        
        long long ans2=1,ans1=1;
        int flog1=0,flog2=0,flog=1,flogg=1;
        for(i=1;i<=n;i++)
        {
        	if(a1[i]==1&&a2[i]=='B'||a1[i]==0)
        	flog=0;
        	if(a1[i]==1&&a2[i]=='R'||a1[i]==0)
        	flogg=0;
        }
        if(flog)flog1++;if(flogg)flog2++;
    	
    	flog=1,flogg=1;
		for(i=1;i<=m;i++)
        {
        	if(b1[i]==1&&b2[i]=='B'||b1[i]==0)
        	flog=0;
        	if(b1[i]==1&&b2[i]=='R'||b1[i]==0)
        	flogg=0;
        }
    	if(flog)flog1++;if(flogg)flog2++;
        
		for(i=1;i<=n;i++)
        {
            ans1=(ans1*a1[i])%mo;
        }
        for(i=1;i<=m;i++)
        {
            ans2=(ans2*b1[i])%mo;
        }
     //   cout<<flog1<<" "<<flog2<<endl;
        cout<<(ans1+ans2+(flog1==2?-1:0)+(flog2==2?-1:0)+mo)%mo<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值