Gym - 100625F Count Ways 快速幂+容斥原理

题意:n*m的格子,中间有若干点不能走,问从左上角到右下角有多少种走法。

思路:CountWay(i,j) 表示从 i 点到 j 点的种数。然后用容斥原理加加减减解决

 

 1 #pragma comment(linker, "/STACK:1000000000")
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <fstream>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <deque>
 8 #include <vector>
 9 #include <queue>
10 #include <string>
11 #include <cstring>
12 #include <map>
13 #include <stack>
14 #include <set>
15 #define LL long long
16 #define MAXN 100005
17 #define MOD 1000000007
18 #define INF 0x3f3f3f3f
19 #define eps 1e-8
20 using namespace std;
21 struct Node
22 {
23     LL x, y;
24 };
25 Node p[MAXN];
26 LL factor[2 * MAXN], w[2 * MAXN];
27 LL res[MAXN];
28 bool compare(Node a, Node b)
29 {
30     return a.x < b.x || (a.x == b.x && a.y < b.y);
31 }
32 LL CountWay(LL x, LL y)
33 {
34     LL res = factor[x + y];
35     res = res * w[x] % MOD;
36     res = res * w[y] % MOD;
37     return res;
38 }
39 LL quick_power(LL x, LL y)
40 {
41     if (y == 0){
42         return (LL)1;
43     }
44     if (y == 1){
45         return x % MOD;
46     }
47     LL res = quick_power(x, y >> 1);
48     res = (res * res) % MOD;
49     if (y & 1){
50         res = (res * x) % MOD;
51     }
52     return res;
53 }
54 int main()
55 {
56 #ifndef ONLINE_JUDGE
57     freopen("in.txt", "r", stdin);
58     //freopen("out.txt", "w", stdout);
59 #endif // OPEN_FILE
60     int T;
61     factor[0] = 1;
62     w[0] = 1;
63     for (LL i = 1; i <= 200000; i++){
64         factor[i] = (factor[i - 1] * i) % MOD;
65         w[i] = quick_power(factor[i], MOD - 2);
66     }
67     scanf("%d", &T);
68     LL n, m, k;
69     while (T--){
70         scanf("%I64d%I64d%I64d", &n, &m, &k);
71         for (int i = 1; i <= k; i++){
72             scanf("%I64d%I64d", &p[i].x, &p[i].y);
73         }
74         p[k + 1].x = n;
75         p[k + 1].y = m;
76         sort(p + 1, p + k + 1, compare);
77         for (int i = 1; i <= k + 1; i++){
78             res[i] = CountWay(p[i].x - 1, p[i].y - 1);
79         }
80         for (int i = 1; i <= k + 1; i++){
81             for (int j = i + 1; j <= k + 1; j++){
82                 if (p[j].x < p[i].x || p[j].y < p[i].y) continue;
83                 //if(p[j].x == p[i].x && p[j].y == p[i].y) continue;
84                 res[j] = (res[j] - (res[i] * CountWay(p[j].x - p[i].x, p[j].y - p[i].y)) % MOD) % MOD;
85             }
86         }
87         printf("%I64d\n", (res[k + 1] + MOD) % MOD);
88     }
89 }

 

posted on 2015-08-14 12:38  张济  阅读(181)  评论(0编辑  收藏  举报

导航