CSP/NOIP新赛制内部挑战赛3 C. maze

 

 

 

 

 

 

 

N = 2时,棋盘上必须无障碍点,且m为奇数时有解,方案数为1.
N = 3时,观察可以发现,中间一行所有的格子一定是必经的,且相邻两个格子为一个单元,同时位于第1行或者第3行。所以每个小单元方案数为2,空棋盘的方案数为2的幂次。
障碍点对于答案的影响是,限制这个单元只能选择第1行或者第3行,因此每限制一个单元,答案除掉一个2.如果一个单元的第一行和第三行都设置了障碍,或者中间第二行有任何障碍,则无解。

N = 3时,数组还开不下,还得用map离散一下

还有蛮多需要注意的细节


代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
int n,m,q;
void solve2()
{
    int x,y;
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&x,&y);
        printf("0\n");
    }
}
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=(res*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return res;
}
ll inv2;
map <int,int> ban[5];
void solve3()
{
    int x,y;
    inv2=qpow(2,mod-2);
    int flag=0;
    ll res=0;
    if(m%2==1) flag=1;
    if(!flag) res=qpow(2,m/2-1);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&x,&y);
        if(x==2|| (x==1 && y==1) ||(x==n && y==m))
            flag=1;
        if(flag)
        {
            printf("0\n");
            continue;
        }
        if(y>1 && y<m && !ban[x][y] && !ban[x][y^1])
            res=res*inv2%mod;
        ban[x][y]=1;
        if(x==1 && (ban[3][y] || ban[3][y^1]))
        {
            flag=1;
            printf("0\n");
            continue;
        }
        if(x==3 && (ban[1][y] || ban[1][y^1]))
        {
            flag=1;
            printf("0\n");
            continue;
        }
        printf("%lld\n",res);
    }
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    if(n==2) solve2();
    if(n==3) solve3();
    return 0;
}

 

posted @ 2020-11-28 19:03  andyc_03  阅读(77)  评论(0编辑  收藏  举报