【LOJ6374】[SDWC2018 Day1]網格

【LOJ6374】[SDWC2018 Day1]網格

題面

loj

題解

先考慮一下沒有限制而且可以同時不走的,那麼顯然行列是獨立的。
\(\text{f}(R,T,M)\)表示某一維走出步數\(R\),走\(T\)格,每步不超過\(M\),令生成函數\(\text{F}(x)=1+x+x^2+\cdots +x^M=\frac {1-x^{M+1}}{1-x}\),那麼我們想求的就是\([x^T]\text{F}(x)^R\)
其中
\( \begin{aligned} \text{[}x^T\text{]} \text{F}(x)^R &=[x^T](\frac {1-x^{M+1}}{1-x})^R\\ &=[x^T](1-x^{M+1})^R(1+x+x^2+\cdots)^R\\ &=[x^T](1-x^{M+1})^R\sum_{i=0}^{\infty}{i+R-1\choose R-1}x^i\\ &=\sum_{i=0}^{\lfloor\frac {T}{M+1}\rfloor}(-1)^i{R\choose i}{R-1+T-i(M+1)\choose R-1} \end{aligned} \)

然後再考慮可以有\((0,0)\)限制的:
可以發現\(\text f(R,T_x,M_x)\times \text f(R,T_y,M_y)\)沒有考慮\((0,0)\),那也就是至多走了\(R\)步的方案數,而非恰好
\(\text g(R,T_x,T_y,M_x,M_y)\)表示恰好\(R\)步,然後裏面參數自己看的答案,二項式反演得:
\(\text g(R,T_x,T_y,M_x,M_y)=\sum_{i=0}^R (-1)^{R-i}{R\choose i}\text f(i,T_x,M_x)\times \text f(i,T_y,M_y)\)

現在再考慮有那\(K\)條限制的:
可以揹包出\(\text h(i,j)\)表示從\(K\)中選了\(i\)步走,走了\(j\times G\)格的方案數,那麼放到總步數\(R\)中,方案數就有\({R \choose i}\text h(i,j)\)種。

最後就可以求出答案了:
考慮容斥,首先枚舉至少踩了\(i\)條限制,再枚舉限制走了\(j\times G\)步,那麼答案爲(不妨令\(T_x<T_y\))

\[Ans=\sum_{i=0}^R(-1)^i{R \choose i}\sum_{j=0}^{\lfloor\frac {T_x}G\rfloor} \text h(i,j)\text g(R-i,T_x-j\times G,T_y-j\times G,M_x,M_y) \]

計算的複雜度爲\(O(R^2\lfloor \frac TG\rfloor)\),可以通過。

代碼

#include <bits/stdc++.h> 
using namespace std; 
int gi() { 
	int res = 0, w = 1; 
	char ch = getchar(); 
	while (ch != '-' && !isdigit(ch)) ch = getchar(); 
	if (ch == '-') w = -1, ch = getchar(); 
	while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar(); 
	return res * w; 
}
const int Mod = 1e9 + 7; 
int fpow(int x, int y) {
	int res = 1; 
	while (y) {
		if (y & 1) res = 1ll * res * x % Mod; 
		x = 1ll * x * x % Mod; 
		y >>= 1; 
	} 
	return res; 
} 
const int MAX_N = 1.2e6 + 5; 
int N = 1.2e6, Tx, Ty, Mx, My; 
int R, G, K, a[55]; 
int fac[MAX_N], ifc[MAX_N]; 
int C(int n, int m) { 
	if (n < m || n < 0 || m < 0) return 0; 
	else return 1ll * fac[n] * ifc[m] % Mod * ifc[n - m] % Mod; 
} 
int f(int R, int T, int M) { 
	int n = T / (M + 1), res = 0; 
	for (int i = 0; i <= n; i++) { 
		int now = 1ll * C(R - 1 + T - i * (M + 1), R - 1) * C(R, i) % Mod; 
		if (i & 1) res = (res - now + Mod) % Mod; 
		else res = (res + now) % Mod; 
	} 
	return res; 
} 
int g(int R, int Tx, int Ty, int Mx, int My) { 
	int res = 0; 
	for (int i = 0; i <= R; i++) { 
		int now = 1ll * C(R, i) * f(i, Tx, Mx) % Mod * f(i, Ty, My) % Mod; 
		if ((R - i) & 1) res = (res - now + Mod) % Mod; 
		else res = (res + now) % Mod; 
	} 
	return res; 
} 
int h[1005][1005]; 
int main () { 
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin);
#endif 
	for (int i = fac[0] = 1; i <= N; i++) fac[i] = 1ll * fac[i - 1] * i % Mod; 
	ifc[N] = fpow(fac[N], Mod - 2); 
	for (int i = N - 1; ~i; i--) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % Mod; 
	Tx = gi(), Ty = gi(), Mx = gi(), My = gi(); 
	R = gi(), G = gi(), K = gi(); 
	for (int i = 1; i <= K; i++) a[i] = gi() / G; 
	sort(&a[1], &a[K + 1]); K = unique(&a[1], &a[K + 1]) - a - 1; 
	h[0][0] = 1; 
	int mx = max(Tx, Ty) / G; 
	for (int i = 1; i <= min(mx, R); i++) 
		for (int j = 1; j <= K; j++) 
			for (int k = a[j]; k <= mx; k++) h[i][k] = (h[i][k] + h[i - 1][k - a[j]]) % Mod;
	int ans = 0; 
	for (int i = 0; i <= R; i++) { 
		int res = 0; 
		for (int j = 0; j <= mx; j++) 
			res = (res + 1ll * h[i][j] * g(R - i, Tx - j * G, Ty - j * G, Mx, My)) % Mod; 
		res = 1ll * res * C(R, i) % Mod; 
		if (i & 1) ans = (ans - res + Mod) % Mod; 
		else ans = (ans + res) % Mod; 
	} 
	printf("%d\n", ans); 
    return 0; 
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章