您的位置:首页 > 其它

Codeforces Gym 100589F Count Ways(DP+组合数学)

2015-10-26 22:18 477 查看

题意:就对于一个H*W的棋盘从点(1, 1)走到(H, W), 每次只能x++或者y++地走, 其中棋盘上有n个点是坏点, 也就是不能走的点, 那么从(1, 1)到(H, W)不经过这n个坏点的路径有多少种, H, W <= 100000, n <= 2000。

思路:组合数学+DP。如果没有坏点的话方案数显然为C(h+w-2, h-1),现在有了坏点,不能直接求出来,考虑DP。

首先将所有坏点按坐标排序,用dp[i]代表到达第i个坏点且之前不经过任何坏点的方案数,

因为到达第i个坏点的所有方案数为C(node[i].x-1+node[i].y-1, node[i].x-1),现在我们只需要减去经过坏点的方案数,根据dp的含义,经过坏点的情况数我们可以通过枚举经过的第一个坏点来求出,具体的状态转移方程为

dp[i] = C(node[i].x-1+node[i].y-1, node[i].x-1) - sigma(dp[j]*C(node[i].x-node[j].x+node[i].y-node[j].y, node[i].x-node[j].x)) (j<i且node[j].y<=node[i].y)。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 1100;
const int MAXM = 2e5+10;
const int MOD = 1e9+7;
int n, m, k;
LL dp[MAXN];
LL jc[MAXM], inv[MAXM];
struct Node {
int x, y;
bool operator < (const Node& A) const {
if(x == A.x) return y < A.y;
return x < A.x;
}
} node[MAXN];
LL pow_mod(LL a, LL b) {
if(!b) return 1;
LL ans = pow_mod(a, b/2);
ans = ans * ans % MOD;
if(b&1) ans = ans * a % MOD;
return ans;
}
void init() {
jc[0] = inv[0] = 1;
for(int i = 1; i <= 2e5; i++) {
jc[i] = jc[i-1] * i % MOD;
inv[i] = inv[i-1] * pow_mod(i, MOD-2) % MOD;
}
}
LL C(int n, int m) {
return jc
* inv[m] % MOD * inv[n-m] % MOD;
}
int main() {
//freopen("input.txt", "r", stdin);
init();
int T; cin >> T;
while(T--) {
memset(dp, 0, sizeof(dp));
cin >> n >> m >> k;
for(int i = 1; i <= k; i++) scanf("%d%d", &node[i].x, &node[i].y);
node[k+1].x = n;
node[k+1].y = m;
sort(node+1, node+k+2);
for(int i = 1; i <= k+1; i++) {
for(int j = 1; j < i; j++) {
if(node[j].y <= node[i].y)
dp[i] = (dp[i]-dp[j]*C(node[i].y-node[j].y+node[i].x-node[j].x, node[i].x-node[j].x)) % MOD;
}
dp[i] = (dp[i]+C(node[i].y-1+node[i].x-1, node[i].x-1)+MOD) % MOD;
}
printf("%I64d\n", dp[k+1]);
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息