HDU 6122 Color the chessboard【思维】

题目链接

题意:n*m的棋盘,每个格点有三种颜色,红色,蓝色或者白色。现在要把所有白色的点都染成红色或者蓝色,要求染完后对于这个棋盘上任意一个偶数长偶数宽的长方形,里面红色的点的个数都等于蓝色的点的个数,求有几种染色方案。

把红色当做1,蓝色当做0。如果现在最左上角是这样的:

1010

那从第三行开始每行的前两个就已经确定了,就是说第三行的前两个是1,1,第四行的前两个是0,0,…

而第三列的前两行的两个数影响了整个表格:

1010101010101010

或者是

1010101001011010

也就是说每行都是 01 循环或者 10 循环或者每列都是 01 循环或者 10 循环。

所以可以对每行先假设它第一个是 1 ,跑一遍看是否可行,再假设是0跑一遍。对每列的情况同理。

然而还有一个问题,在下面这两种情况下,可以同时看做每行的 10 或者 01 循环或者是每列的 10 或者 01 循环。

1010010110100101

或者

0101101001011010

所以要再特地去跑一遍这两种情况,如果能满足的话就减1。

其实这题不是很难,但是比赛的时候没去看 :(

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int mod=998244353;

int T;
int n,m;
char a[1050][1050];

int main(){
    scanf("%d",&T);
    while (T--){
        scanf("%d %d",&n,&m);
        for (int i=1;i<=n;i++){
            scanf("%s",a[i]+1);
        }
        ll ans1=1;
        for (int i=1;i<=n;i++){
            int cnt=0;
            bool flag=true;
            for (int j=1;j<=m;j++){
                if (j%2==0){
                    if (a[i][j]=='R')   flag=false;
                }
                else{
                    if (a[i][j]=='B')   flag=false;
                }
            }
            if (flag)   cnt++;
            flag=true;
            for (int j=1;j<=m;j++){
                if (j%2==0){
                    if (a[i][j]=='B')   flag=false;
                }
                else{
                    if (a[i][j]=='R')   flag=false;
                }
            }
            if (flag)   cnt++;
            ans1=ans1*cnt%mod;
        }
        ll ans2=1;
        for (int j=1;j<=m;j++){
            int cnt=0;
            bool flag=true;
            for (int i=1;i<=n;i++){
                if (i%2==1){
                    if (a[i][j]=='R')   flag=false;
                }
                else{
                    if (a[i][j]=='B')   flag=false;
                }
            }
            if (flag)   cnt++;
            flag=true;
            for (int i=1;i<=n;i++){
                if (i%2==1){
                    if (a[i][j]=='B')   flag=false;
                }
                else{
                    if (a[i][j]=='R')   flag=false;
                }
            }
            if (flag)   cnt++;
            ans2=ans2*cnt%mod;
        }
        ll ans=(ans1+ans2)%mod;
        bool flag=true;
        for (int i=1;i<=n;i++){
            for (int j=1;j<=m;j++){
                if ((i+j)%2==1){
                    if (a[i][j]=='R')   flag=false;
                }
                else{
                    if (a[i][j]=='B')   flag=false;
                }
            }
        }
        if (flag)   ans=(ans-1+mod)%mod;
        flag=true;
        for (int i=1;i<=n;i++){
            for (int j=1;j<=m;j++){
                if ((i+j)%2==1){
                    if (a[i][j]=='B')   flag=false;
                }
                else{
                    if (a[i][j]=='R')   flag=false;
                }
            }
        }
        if (flag)   ans=(ans-1+mod)%mod;
        printf("%lld\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值