kmjp's blog

競技プログラミング参加記です

yukicoder : No.2572 Midori on the grid

これはライブラリがあったので簡単だった…。
https://yukicoder.me/problems/no/2572

問題

(0,0)から、右または上の格子点をたどり、(X,Y)に到達したい。
この際、以下のクエリに答えよ。

整数tが指定されるので、直線y=x+tを経由しない到達方法は何通りか。

解法

t>0の場合を考える。t<0の場合、X軸とY軸を入れ替えればよい。
Y≧X+Tの時は明らかに解0。
それ以外の場合、カタラン数の考え方を応用すると、C(X+Y,Y)-C(X+Y,Y-T)になる。

int H,W,Q;
const ll mo=998244353;
ll comb(ll N_, ll C_) {
	const int NUM_=3400001;
	static ll fact[NUM_+1],factr[NUM_+1],inv[NUM_+1];
	if (fact[0]==0) {
		inv[1]=fact[0]=factr[0]=1;
		for (int i=2;i<=NUM_;++i) inv[i] = inv[mo % i] * (mo - mo / i) % mo;
		for (int i=1;i<=NUM_;++i) fact[i]=fact[i-1]*i%mo, factr[i]=factr[i-1]*inv[i]%mo;
	}
	if(C_<0 || C_>N_) return 0;
	return factr[C_]*fact[N_]%mo*factr[N_-C_]%mo;
}

ll catalan_arrange(int X,int Y,int T=1) {
	if(X+T<=Y) return 0;
	return (comb(X+Y,Y)-comb(X+Y,Y-T)+mo)%mo;
}

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>H>>W>>Q;
	while(Q--) {
		int T;
		cin>>T;
		
		if(T>0) {
			cout<<catalan_arrange(H,W,T)<<endl;
		}
		else {
			cout<<catalan_arrange(W,H,-T)<<endl;
		}
		
	}
	
	
}

まとめ

ライブラリにしてないともうちょい苦戦してたかも。