2019 ICPC Asia-East Continent Final 部分题题解

题面

Problem B. Black and White

题目大意:有一个\(n\) \(\times\) \(m\)的网格,网格之中的格子有黑白两种颜色。
被(0,0),(0,1),(1,0),(1,1)包围的格子是白色,一个格子周围的四个格子的颜色与其都不相同。
现要从(0,0)走到(n,m),每次只能向上或向右走。
给定\(k\),求满足条件的路径数量,使得这条路径左边的白格子数-黑格子数=\(k\)
多组数据。
\(n,m,|w| \leq 1e5\)\(T \leq 100\)
题解:
设当前白格子数-黑格子数为\(w\)
发现每次如果只走一步,我们没法判断当前的\(w\)的变化量。那么考虑走两步。
如果每次都走两步的话,那无非就四种情况:
1.\(\rightarrow \rightarrow\)
2.\(\uparrow \uparrow\)
3.\(\uparrow \rightarrow\)
4.\(\rightarrow \uparrow\)
前两种情况对\(w\)无影响,而3,4这两种情况可能会对\(w\)造成影响。
考虑枚举3,4操作的总次数\(p\),以及4操作的次数\(q\)
通过打表,可以发现一个式子:

\[\lfloor \frac{p+1}{2} \rfloor - q = k \]

由此,我们只需要枚举\(p\),就能得到合法的\(q\)了。
现在考虑统计方案数。
\(x=\frac{n+m}{2}\),那么相当于在\(x\)次操作中任选\(p\)次,又在\(p\)次中任选\(q\)个。
然后情况1,2的组合,就是在\(x-p\)次中选\(\frac{n-p}{2}\)次。也就是三个组合数。
注意所有这些要除以2的地方都要求是偶数才有意义。
如果\(n+m\)是奇数,讨论一下第一步怎么走,然后正常算两次就好了。
时间复杂度:\(O(Tn)\)
代码:

#include
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define STS system("pause")
templateI read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
const int Mod=998244353,N=100010;
int T,fac[101000],inv[101000];
I add(int &x,int y){(x+=y)>=Mod?x-=Mod:0;}
IN Plus(int x,int y){(x+=y)>=Mod?x-=Mod:0;return x;}
IN Pow(int x,int y=Mod-2){
	re res=1;
	while(y){
		if(y&1)res=(ll)res*x%Mod;
		x=(ll)x*x%Mod;
		y>>=1;
	}
	return res;
}
IN C(int x,int y){if(x>1,ans=0;
//	cout<>1)-k;
		if(q<0||q>p||((n-p)&1)||p>n)continue;
//		cout<<"!"<>1)%Mod);
	}
	return ans;
}
int n,m,k;
int main(){
	read(T);init();
	while(T--){
		read(n);read(m);read(k);
		if(!((n+m)&1))printf("%d\n",solve(n,m,k));
		else printf("%d\n",Plus(solve(n-1,m,-k),solve(n,m-1,(n&1)-k)));
	}
	return 0;
}
/*
5
1 1 0
1 1 -1
2 2 1
2 2 0
4 4 1
*/

你可能感兴趣的:(2019 ICPC Asia-East Continent Final 部分题题解)