題解 AT1974 【[ARC058B] いろはちゃんとマス目 / Iroha and a Grid】
阿新 • • 發佈:2020-11-23
題意:
給出一個\(H \times W\)的矩陣,將左下角挖去一個\(A \times B\)的小矩陣,求從左上角走到右下角的方案數。
首先看好邊界問題,實際上只走了\(H + W - 2\)步。
思路:
這道題第一眼看上去有點容斥的意思,考慮怎麼求答案
如果沒有小矩陣,那麼方案數很顯然是 \(C_{H + W - 2}^{H - 1}\),但是有了小矩陣,那麼只需要把經過小矩陣的答案的貢獻減去就好了。
再考慮怎麼算經過小矩陣的方案數,首先暴力列舉一個位置\(i\)(小矩陣的上沿),即這條路線在該位置第一次經過小矩陣,此時一定是不合法的方案了,剩下的步數為\(W - i + A - 1\)
\(C_{H + W - 2}^{H - 1} - \sum\limits_{i = 1}^{B - 1} C_{H - A + i - 1}^{H - A} \times C_{W - i + A - 2}^{W - i} - C_{H - A + B - 1}^{H - A} \times C_{W - B + A - 1}^{W - B}\)
程式碼實現:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; #define int long long const int maxn = 2e6 + 50, mod = 1e9 + 7; long long H, W, A, B; long long jc[maxn], ny[maxn], jcny[maxn]; void init () { jc[1] = ny[1] = jcny[1] = jcny[0] = 1; long long a, b; for (register long long i = 2; i <= maxn - 5; ++i) { jc[i] = jc[i - 1] * i % mod; a = mod / i, b = mod % i; ny[i] = (-a * ny[b] % mod + mod) % mod; jcny[i] = jcny[i - 1] * ny[i] % mod; } } inline long long C (int a, int b) { if (a == 0 || b == 0 || a == b) return 1; return jc[a] * jcny[b] % mod * jcny[a - b] % mod; } long long ans; signed main () { init(); scanf ("%lld%lld%lld%lld", &H, &W, &A, &B); ans = C(H + W - 2, H - 1); for (register int i = 1; i < B; i++) { ans = ((ans - (C(H - A + i - 1, H - A) * C(W - i + A - 2, W - i) % mod)) % mod + mod) % mod; } ans = ans = ((ans - (C(H - A + B - 1, H - A) * C(W- B + A - 1, W - B) % mod)) % mod + mod) % mod; cout<<ans<<endl; return 0; }