题解:P11704 [ROIR 2025] 旅行路线
Egg_eating_master · · 题解
题意:两条从
首先这两条路径一定是一条从
考虑不要求两条路径不交怎么做。我们 DP 即可,设
然后考虑减掉相交的方案数。我们钦定两条路径在第一次相交的位置“互换身份”,那么就变成了一条从
注意需要特判
然后就做完了!
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 2010, maxm = 2000005, mod = 1e9 + 7;
int n, m, k;
struct node {
int x, y;
bool operator < (const node &a) const {return x + y < a.x + a.y;}
} a[maxn];
int dp[maxn][maxn];
int fac[maxm], ifac[maxm];
int power(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod; b >>= 1;
}
return res;
}
void init(int n) {
fac[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % mod;
ifac[n] = power(fac[n], mod - 2);
for (int i = n - 1; i >= 0; i--) ifac[i] = ifac[i + 1] * (i + 1) % mod;
}
int C(int n, int m) {
if (m < 0 || m > n) return 0;
return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
int calc(int p, int q) {return C(a[q].x + a[q].y - a[p].x - a[p].y, a[q].x - a[p].x);}
int solve(int p, int q) {
for (int i = 1; i <= k; i++)
for (int j = 1; j <= k; j++)
dp[i][j] = 0;
dp[p][q] = 1;
for (int i = 3; i <= k; i++) {
for (int j = 1; j <= i - 2; j++) {
dp[i - 1][i] = (dp[i - 1][i] + dp[i - 1][j] * calc(j, i)) % mod;
dp[i][j] = (dp[i][j] + dp[i - 1][j] * calc(i - 1, i)) % mod;
dp[i][i - 1] = (dp[i][i - 1] + dp[j][i - 1] * calc(j, i)) % mod;
dp[j][i] = (dp[j][i] + dp[j][i - 1] * calc(i - 1, i)) % mod;
}
}
return dp[k - 1][k];
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m >> k; init(n + m);
a[1] = (node){2, 1}, a[2] = (node){1, 2};
for (int i = 3; i <= k + 2; i++) {
cin >> a[i].x >> a[i].y;
if (a[i].x == 1 && a[i].y == 1) i--, k--;
if (a[i].x == n && a[i].y == m) i--, k--;
}
a[k + 3] = (node){n, m - 1}, a[k + 4] = (node){n - 1, m};
sort(a + 3, a + k + 3);
k += 4;
cout << (solve(1, 2) - solve(2, 1) + mod + mod) * 2 % mod << '\n';
return 0;
}