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