Google Code Jam 2008 Round 3 解题报告
Problem A: How Big Are the Pockets?
这题的意思是要求一个闭合的多边形外,有多少点的上和下或者左和右都有多边形的边界。
假设我们一行一行地来扫描这个多边形,我们从最左边开始,这时候我们的点在多边形外。
当我们第一次穿过多边形的一个边界的时候,很明显,我们就进入了多边形的内部,当再次遇到一条边界的时候我们又在多边形的外部了。通过这样的方法,我们可以发现当我们把某一行的边界按照坐标排序后第偶数条边界同第奇数条边界之间的所有点都是在多边形外部的,并且他们有左右两个边界。对于竖直方向上我们也可以用类似的方法处理。

 Code
Code1

 /**//*
/**//*2
 GCJ'08 Problem A
    GCJ'08 Problem A3
 Author Nicholas
  Author Nicholas4
 */
*/5

6
 #include <iostream>
#include <iostream>7
 #include <set>
#include <set>8
 #include <vector>
#include <vector>9
 #include <algorithm>
#include <algorithm>10

11

12

13

14
 using namespace std;
using namespace std;15

16

 const int dir[4][2] =
const int dir[4][2] =  {
{ {1,0},
{1,0},  {0,1},
{0,1},  {-1,0},
{-1,0},  {0,-1}};
{0,-1}};17

18
 vector<int> ver[10000], hor[10000];
vector<int> ver[10000], hor[10000];19

20

21
 int main()
int main()22


 {
{23
 freopen("in.txt","r", stdin);
    freopen("in.txt","r", stdin);24
 freopen("out.txt", "w", stdout);
    freopen("out.txt", "w", stdout);25
 int T;
    int T;26
 scanf("%d", &T);
    scanf("%d", &T);27

28
 for (int ctr = 1; ctr <= T; ctr++)
    for (int ctr = 1; ctr <= T; ctr++)29

 
     {
{30
 int L;
        int L;31
 scanf("%d", &L);
        scanf("%d", &L);32
 int x = 5000, y = 5000, nd = 0;
        int x = 5000, y = 5000, nd = 0;33

34
 for (int i = 0; i < 10000; i++)
        for (int i = 0; i < 10000; i++)35
 ver[i].clear(), hor[i].clear();
            ver[i].clear(), hor[i].clear();36

37
 for (int i = 0; i < L; i++)
        for (int i = 0; i < L; i++)38

 
         {
{39
 char s[1000];
            char s[1000];40
 int t;
            int t;41
 scanf("%s%d", s, &t);
            scanf("%s%d", s, &t);42
 for (int rep = 0; rep < t; rep++)
            for (int rep = 0; rep < t; rep++)43

 
             {
{44
 for (int j = 0; j < strlen(s); j++)
                for (int j = 0; j < strlen(s); j++)45

 
                 {
{46
 
                    47
 int nx, ny;
                    int nx, ny;48
 switch (s[j])
                    switch (s[j])49

 
                     {
{50
 case 'R' : nd = (nd + 1) & 3; break;
                        case 'R' : nd = (nd + 1) & 3; break;51
 case 'L' : nd = (nd + 3) & 3; break;
                        case 'L' : nd = (nd + 3) & 3; break;52
 case 'F' :
                        case 'F' :53
 nx = x + dir[nd][0], ny = y + dir[nd][1];
                                    nx = x + dir[nd][0], ny = y + dir[nd][1];54
 if (y != ny)
                                    if (y != ny)55
 hor[min(y, ny)].push_back(x);
                                        hor[min(y, ny)].push_back(x);56
 else
                                    else57
 ver[min(x, nx)].push_back(y);
                                        ver[min(x, nx)].push_back(y);58
 x = nx, y = ny;
                                        x = nx, y = ny;59
 break;
                                    break;60
 }
                    }61
 
                62
 }
                }63

64
 }
            }65
 }
        }66

67
 set<int> pockets[10000];
        set<int> pockets[10000];68

69
 for (int i = 0; i < 10000; i++)
        for (int i = 0; i < 10000; i++)70
 sort(ver[i].begin(), ver[i].end()), sort(hor[i].begin(), hor[i].end());
            sort(ver[i].begin(), ver[i].end()), sort(hor[i].begin(), hor[i].end());71

72

73
 for (int x = 0; x < 10000; x++)
        for (int x = 0; x < 10000; x++)74
 for (int j = 1; j + 1 < ver[x].size(); j+=2)
            for (int j = 1; j + 1 < ver[x].size(); j+=2)75

 
             {
{76
 int y1 = ver[x][j], y2 = ver[x][j+1];
                int y1 = ver[x][j], y2 = ver[x][j+1];77
 for (int y = y1; y < y2; y++)
                for (int y = y1; y < y2; y++)78
 pockets[x].insert(y);
                    pockets[x].insert(y);79
 }
            }80

81
 
        82
 
        83
 for (int y = 0; y < 10000; y++)
        for (int y = 0; y < 10000; y++)84
 for (int j = 1; j + 1 < hor[y].size(); j+=2)
            for (int j = 1; j + 1 < hor[y].size(); j+=2)85

 
             {
{86
 int x1 = hor[y][j], x2 = hor[y][j+1];
                int x1 = hor[y][j], x2 = hor[y][j+1];87
 
            88
 for (int x = x1; x < x2; x++)
                for (int x = x1; x < x2; x++)89
 pockets[x].insert(y);
                    pockets[x].insert(y);90
 }
            }91

92
 int ret = 0;
            int ret = 0;93
 for (int i = 0; i < 10000; i++)
            for (int i = 0; i < 10000; i++)94
 ret += pockets[i].size();
                ret += pockets[i].size();95

96
 printf("Case #%d: %d\n", ctr, ret);
            printf("Case #%d: %d\n", ctr, ret);97
 }
    }98

99
 return 0;
    return 0;100
 }
}101

Probles B: Portal
题目的意思就是在一个迷宫内从一个点以最短的步数走到另一个点,不过我们可以使用传送门。
基本的方法是BFS。关键在于怎么记录状态,起初我是想记录下当前人所在的坐标以及两个门的坐标以及门的方向,这样需要 17^6×8的空间,显然这个方法不太好。在仔细想想,我们发现第一枪是可以随便打的,可是当我们打出第二枪的时候,我们就一定会朝着第二枪所打的方向一直走过去,并穿过那个传送门,应为如果不这样走的话,那么,那个第二枪打的是没有意义的。进一步思考,我们还会发现,第二枪一定可以是贴着墙打的,不是吗?
这样我们我们就需要记录到某个点坐标,以及到该点时所有可能有门的位置。然后当我们走到一面墙的时候,就可能到其他所有有门的位置了。

 Code
Code1

 /**//*
/**//*2
 GCJ'08 Problem B
    GCJ'08 Problem B3
 Author Nicholas
  Author Nicholas4
 */
*/5
 #include <iostream>
#include <iostream>6
 #include <string>
#include <string>7
 #include <queue>
#include <queue>8

9
 using namespace std;
using namespace std;10

11

 const int dir[4][2] =
const int dir[4][2] =  {
{ {-1,0},
{-1,0},  {0, 1},
{0, 1},  {1,0},
{1,0},  {0, -1}};
{0, -1}};12

13
 struct state
struct state14


 {
{15
 int x,y;
    int x,y;16
 short int p[16];
    short int p[16];17
 };
};18

19
 struct pos
struct pos20


 {
{21
 int x, y;
    int x, y;22
 };
};23

24
 char G[32][32];
char G[32][32];25

26
 pos nw[32][32][4];
pos nw[32][32][4];27
 int dp[32][32];
int dp[32][32];28

29

30

31
 int main()
int main()32


 {
{33
 int T;
    int T;34
 freopen("in.txt", "r", stdin);
    freopen("in.txt", "r", stdin);35
 freopen("out.txt", "w", stdout);
    freopen("out.txt", "w", stdout);36
 scanf("%d", &T);
    scanf("%d", &T);37
 for (int ctr = 1; ctr <= T; ctr++)
    for (int ctr = 1; ctr <= T; ctr++)38

 
     {
{39
 int R, C;
        int R, C;40
 memset(dp, 63, sizeof(dp));
        memset(dp, 63, sizeof(dp));41

42
 scanf("%d%d", &R, &C);
        scanf("%d%d", &R, &C);43
 for (int i = 0; i <= C +1; i++)
        for (int i = 0; i <= C +1; i++)44

 
         {
{45
 G[0][i] = G[R+1][i] = '#';
            G[0][i] = G[R+1][i] = '#';46
 }
        }47

48
 for (int i = 1; i <= R; i++)
        for (int i = 1; i <= R; i++)49

 
         {
{50
 G[i][0] = '#';
            G[i][0] = '#';51
 scanf("%s", G[i]+1);
            scanf("%s", G[i]+1);52
 G[i][C+1] = '#';
            G[i][C+1] = '#';53
 }
        }54
 queue<state> Q;
        queue<state> Q;55
 state start;
        state start;56
 bool flag = true;
        bool flag = true;57
 for (int i = 1; i <= R && flag; i++)
        for (int i = 1; i <= R && flag; i++)58
 for (int j = 1; j <= C; j++)
            for (int j = 1; j <= C; j++)59
 if (G[i][j] == 'O')
                if (G[i][j] == 'O')60

 
                 {
{61
 start.x = i;
                    start.x = i;62
 start.y = j;
                    start.y = j;63
 memset(start.p, 0, sizeof(start.p));
                    memset(start.p, 0, sizeof(start.p));64
 flag = false;
                    flag = false;65
 break;
                    break;66
 }
                }67
 Q.push(start);
        Q.push(start);68
 dp[ start.x ][ start.y ] = 0;
        dp[ start.x ][ start.y ] = 0;69

70
 for (int i = 1; i <= R; i++)
        for (int i = 1; i <= R; i++)71
 for (int j = 1; j <= C; j++)
            for (int j = 1; j <= C; j++)72
 if (G[i][j] != '#')
                if (G[i][j] != '#')73

 
                 {
{74
 for (int d = 0; d < 4; d++)
                    for (int d = 0; d < 4; d++)75

 
                     {
{76
 nw[i][j][d].x = i + dir[d][0];
                        nw[i][j][d].x = i + dir[d][0];77
 nw[i][j][d].y = j + dir[d][1];
                        nw[i][j][d].y = j + dir[d][1];78
 while ( G[ nw[i][j][d].x ][ nw[i][j][d].y ] != '#' )
                        while ( G[ nw[i][j][d].x ][ nw[i][j][d].y ] != '#' )79
 nw[i][j][d].x += dir[d][0],    nw[i][j][d].y += dir[d][1];
                            nw[i][j][d].x += dir[d][0],    nw[i][j][d].y += dir[d][1];80
 nw[i][j][d].x -= dir[d][0];
                        nw[i][j][d].x -= dir[d][0];81
 nw[i][j][d].y -= dir[d][1];
                        nw[i][j][d].y -= dir[d][1];82
 }
                    }83

84
 }
                }85
 while (!Q.empty())
        while (!Q.empty())86

 
         {
{87
 state cs = Q.front();
            state cs = Q.front();88
 Q.pop();
            Q.pop();89
 int &x = cs.x, &y = cs.y;
            int &x = cs.x, &y = cs.y;90
 if (G[x][y] == 'X') break;
            if (G[x][y] == 'X') break;91
 short int *p = cs.p;
            short int *p = cs.p;92
 for (int d = 0; d < 4; d++)
            for (int d = 0; d < 4; d++)93

 
             {
{94
 int wx = nw[x][y][d].x;
                int wx = nw[x][y][d].x;95
 int wy = nw[x][y][d].y;
                int wy = nw[x][y][d].y;96
 if ( ! ((1<<wy)&p[wx]) )
                if ( ! ((1<<wy)&p[wx]) )97

 
                 {
{98
 p[wx] |= (1<<wy);
                    p[wx] |= (1<<wy);99
 }
                }100
 }
            }101
 for (int d = 0; d < 4; d++)
            for (int d = 0; d < 4; d++)102

 
             {
{103
 int nx = x + dir[d][0];
                int nx = x + dir[d][0];104
 int ny = y + dir[d][1];
                int ny = y + dir[d][1];105
 if (G[nx][ny] != '#')
                if (G[nx][ny] != '#')106

 
                 {
{107
 if (dp[nx][ny] > dp[x][y] + 1)
                    if (dp[nx][ny] > dp[x][y] + 1)108

 
                     {
{109
 state temp = cs;
                        state temp = cs;110
 temp.x = nx;
                        temp.x = nx;111
 temp.y = ny;
                        temp.y = ny;112
 dp[nx][ny] = dp[x][y] + 1;
                        dp[nx][ny] = dp[x][y] + 1;113
 Q.push(temp);
                        Q.push(temp);114
 }
                    }115
 }
                }116
 else
                else117

 
                 {
{118
 for (int i = 1; i <= R; i++)
                    for (int i = 1; i <= R; i++)119
 for (int j = 1; j <= C; j++)
                        for (int j = 1; j <= C; j++)120
 if ( ((1<<j)&p[i]) && dp[i][j] > dp[x][y] + 1)
                         if ( ((1<<j)&p[i]) && dp[i][j] > dp[x][y] + 1)121

 
                             {
{122
 state temp = cs;
                                state temp = cs;123
 temp.x = i, temp.y = j;
                                temp.x = i, temp.y = j;124
 dp[i][j] = dp[x][y] + 1;
                                dp[i][j] = dp[x][y] + 1;125
 Q.push(temp);
                                Q.push(temp);126
 }
                            }127
 }
                }128
 }
            }129

130

131
 }
        }132

133
 int ex = 0, ey;
        int ex = 0, ey;134
 for (int i = 1; i <= R && !ex; i++)
        for (int i = 1; i <= R && !ex; i++)135
 for (int j = 1; j <= C; j++)
            for (int j = 1; j <= C; j++)136
 if (G[i][j] == 'X')
                if (G[i][j] == 'X')137

 
                 {
{138
 ex = i, ey = j;
                    ex = i, ey = j;139
 break;
                    break;140
 }
                }141

142
 printf("Case #%d: ", ctr);
        printf("Case #%d: ", ctr);143
 if (dp[ex][ey] < 1000000) printf("%d\n", dp[ex][ey]);
        if (dp[ex][ey] < 1000000) printf("%d\n", dp[ex][ey]);144
 else
        else145
 printf("THE CAKE IS A LIE\n");
            printf("THE CAKE IS A LIE\n");146
 }
    }147
 return 0;
    return 0;148
 }
}
Problem C: No Cheating
这题是很经典的一个问题,比赛的时候我竟然还不知道。
将这个图上的点染成黑白两色,奇数列点染成黑色,偶数列点染成白色。所有冲突的点之间连一条边,我们发现只有黑色点和白色点之间有边。于是问题就转化成了求一个二分图的最大独立集。类似的匹配问题有很多,如PKU 3020 (最少边点覆盖), PKU 3041(最少顶点覆盖)。
我的代码忘了存了,这是bmerry的

 Code
Code1
 #include <string>
#include <string>2
 #include <vector>
#include <vector>3
 #include <map>
#include <map>4
 #include <cstdlib>
#include <cstdlib>5
 #include <cstring>
#include <cstring>6
 #include <cassert>
#include <cassert>7
 #include <set>
#include <set>8
 #include <iostream>
#include <iostream>9
 #include <sstream>
#include <sstream>10
 #include <cstddef>
#include <cstddef>11
 #include <algorithm>
#include <algorithm>12
 #include <utility>
#include <utility>13
 #include <iterator>
#include <iterator>14
 #include <numeric>
#include <numeric>15
 #include <list>
#include <list>16
 #include <complex>
#include <complex>17
 #include <cstdio>
#include <cstdio>18

19
 using namespace std;
using namespace std;20

21
 typedef vector<int> vi;
typedef vector<int> vi;22
 typedef vector<string> vs;
typedef vector<string> vs;23
 typedef long long ll;
typedef long long ll;24
 typedef complex<double> pnt;
typedef complex<double> pnt;25
 typedef pair<int, int> pii;
typedef pair<int, int> pii;26

27
 #define RA(x) (x).begin(), (x).end()
#define RA(x) (x).begin(), (x).end()28
 #define FE(i, x) for (typeof((x).begin()) i = (x).begin(); i != (x).end(); i++)
#define FE(i, x) for (typeof((x).begin()) i = (x).begin(); i != (x).end(); i++)29
 #define SZ(x) ((int) (x).size())
#define SZ(x) ((int) (x).size())30

31
 template<class T>
template<class T>32
 void splitstr(const string &s, vector<T> &out)
void splitstr(const string &s, vector<T> &out)33


 {
{34
 istringstream in(s);
    istringstream in(s);35
 out.clear();
    out.clear();36
 copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));37
 }
}38

39

 template<class T> T gcd(T a, T b)
template<class T> T gcd(T a, T b)  { return b ? gcd(b, a % b) : a; }
{ return b ? gcd(b, a % b) : a; }40

41
 static bool done[10000];
static bool done[10000];42
 static int back[10000];
static int back[10000];43
 static vector<int> edges[10000];
static vector<int> edges[10000];44

45
 static bool augment(int x)
static bool augment(int x)46


 {
{47
 if (x == -1)
    if (x == -1)48
 return true;
        return true;49
 else if (done[x])
    else if (done[x])50
 return false;
        return false;51
 done[x] = true;
    done[x] = true;52

53
 for (int i = 0; i < SZ(edges[x]); i++)
    for (int i = 0; i < SZ(edges[x]); i++)54

 
     {
{55
 int y = edges[x][i];
        int y = edges[x][i];56
 int old = back[y];
        int old = back[y];57
 back[y] = x;
        back[y] = x;58
 if (augment(old))
        if (augment(old))59
 return true;
            return true;60
 back[y] = old;
        back[y] = old;61
 }
    }62
 return false;
    return false;63
 }
}64

65
 int main()
int main()66


 {
{67
 int cases;
    int cases;68
 cin >> cases;
    cin >> cases;69
 for (int cas = 0; cas < cases; cas++)
    for (int cas = 0; cas < cases; cas++)70

 
     {
{71
 int R, C;
        int R, C;72
 int id[100][100];
        int id[100][100];73

 int pool[2] =
        int pool[2] =  {0, 0};
{0, 0};74
 cin >> R >> C;
        cin >> R >> C;75
 for (int i = 0; i < R; i++)
        for (int i = 0; i < R; i++)76

 
         {
{77
 string l;
            string l;78
 cin >> l;
            cin >> l;79
 for (int j = 0; j < C; j++)
            for (int j = 0; j < C; j++)80

 
             {
{81
 if (l[j] == '.')
                if (l[j] == '.')82
 id[i][j] = pool[j & 1]++;
                    id[i][j] = pool[j & 1]++;83
 else
                else84
 id[i][j] = -1;
                    id[i][j] = -1;85
 }
            }86
 }
        }87
 for (int i = 0; i < 10000; i++)
        for (int i = 0; i < 10000; i++)88
 edges[i].clear();
            edges[i].clear();89
 for (int i = 0; i < R; i++)
        for (int i = 0; i < R; i++)90
 for (int j = 0; j < C; j += 2)
            for (int j = 0; j < C; j += 2)91
 if (id[i][j] != -1)
                if (id[i][j] != -1)92

 
                 {
{93
 int x = id[i][j];
                    int x = id[i][j];94
 if (j > 0 && id[i][j - 1] != -1)
                    if (j > 0 && id[i][j - 1] != -1)95
 edges[x].push_back(id[i][j - 1]);
                        edges[x].push_back(id[i][j - 1]);96
 if (j < C - 1 && id[i][j + 1] != -1)
                    if (j < C - 1 && id[i][j + 1] != -1)97
 edges[x].push_back(id[i][j + 1]);
                        edges[x].push_back(id[i][j + 1]);98
 if (i > 0)
                    if (i > 0)99

 
                     {
{100
 if (j > 0 && id[i - 1][j - 1] != -1)
                        if (j > 0 && id[i - 1][j - 1] != -1)101
 edges[x].push_back(id[i - 1][j - 1]);
                            edges[x].push_back(id[i - 1][j - 1]);102
 if (j < C - 1 && id[i - 1][j + 1] != -1)
                        if (j < C - 1 && id[i - 1][j + 1] != -1)103
 edges[x].push_back(id[i - 1][j + 1]);
                            edges[x].push_back(id[i - 1][j + 1]);104
 }
                    }105
 if (i < R - 1)
                    if (i < R - 1)106

 
                     {
{107
 if (j > 0 && id[i + 1][j - 1] != -1)
                        if (j > 0 && id[i + 1][j - 1] != -1)108
 edges[x].push_back(id[i + 1][j - 1]);
                            edges[x].push_back(id[i + 1][j - 1]);109
 if (j < C - 1 && id[i + 1][j + 1] != -1)
                        if (j < C - 1 && id[i + 1][j + 1] != -1)110
 edges[x].push_back(id[i + 1][j + 1]);
                            edges[x].push_back(id[i + 1][j + 1]);111
 }
                    }112
 }
                }113

114
 memset(back, -1, sizeof(back));
        memset(back, -1, sizeof(back));115
 int ans = pool[0] + pool[1];
        int ans = pool[0] + pool[1];116
 for (int i = 0; i < pool[0]; i++)
        for (int i = 0; i < pool[0]; i++)117

 
         {
{118
 memset(done, 0, sizeof(done));
            memset(done, 0, sizeof(done));119
 if (augment(i))
            if (augment(i))120
 ans--;
                ans--;121
 }
        }122
 printf("Case #%d: %d\n", cas + 1, ans);
        printf("Case #%d: %d\n", cas + 1, ans);123
 }
    }124
 return 0;
    return 0;125
 }
}126

Problem D: Endless Knight
题目是一个马,走日字行,不能回头,问从一个棋盘的左上角走到右下角有多少种方法,另外棋盘中还有R(R <= 10)个点是不能走得。
首先我们考虑没有不能走的点的情况,从(1,1)走到(H,W),总共需要走的步数是 Step = (H-1 + W-1) / 3,当然如果不能整除的话,就无法走到终点。如果能走到的话方案总数就是 C[step][H-1-step] (C[i][j] 为组合数)。然后我们要做的就是去除掉这么多方案中所有经过了R中1个或多个点的情况,这里我需要用到容斥原理,具体方法见代码。
最后还有个需要解决的问题就是如何计算 C[m][n] % p,m,n的范围达到10^8。
公式是 C[m][n] % p = C[m/p][n/p] * C[m%p][n%p] % p。别人告诉我的, 有谁知道怎么推导的麻烦告诉我一下子。

 Code
Code
 /**//*
/**//* GCJ'08 Problem D
    GCJ'08 Problem D Author Nicholas
  Author Nicholas */
*/ #include <iostream>
#include <iostream> #include <cstdio>
#include <cstdio> #include <cstring>
#include <cstring> #include <cmath>
#include <cmath> #include <string>
#include <string> #include <cstdlib>
#include <cstdlib> #include <sstream>
#include <sstream> #include <vector>
#include <vector> #include <algorithm>
#include <algorithm> #include <functional>
#include <functional> using namespace std;
using namespace std;
 const double PI = acos(-1.0);
const double PI = acos(-1.0); const int MAXINT = 0x7FFFFFFF;
const int MAXINT = 0x7FFFFFFF; typedef long long LL;
typedef long long LL;


 const int MOD = 10007;
const int MOD = 10007; struct pos
struct pos

 {
{ int x, y;
    int x, y; };
};
 LL C[MOD+1][MOD+1];
LL C[MOD+1][MOD+1];

 pos forb[16];
pos forb[16]; int H, W, R;
int H, W, R;

 LL Calc2(int m, int n)
LL Calc2(int m, int n)

 {
{ if (m > MOD || n > MOD)
    if (m > MOD || n > MOD) return Calc2(m / MOD, n / MOD) * Calc2(m % MOD, n % MOD) % MOD;
        return Calc2(m / MOD, n / MOD) * Calc2(m % MOD, n % MOD) % MOD; return C[m][n];
    return C[m][n]; }
}
 LL Calc(int x, int y)
LL Calc(int x, int y)

 {
{ 
     int step = (x + y) / 3;
    int step = (x + y) / 3; if (step * 3 != x + y) return 0;
    if (step * 3 != x + y) return 0; if (step > x) return 0;
    if (step > x) return 0; if (3 * step - x != y) return 0;
    if (3 * step - x != y) return 0;
 return Calc2(step, x-step);
    return Calc2(step, x-step); }
}
 bool cmp(const pos a, const pos b)
bool cmp(const pos a, const pos b)

 {
{ if (a.x != b.x) a.x < b.x;
    if (a.x != b.x) a.x < b.x; return a.y < b.y;
    return a.y < b.y;
 }
}
 LL Solve(int x)
LL Solve(int x)

 {
{ LL ret = 1;
    LL ret = 1; vector<pos> loc;
    vector<pos> loc; loc.clear ();
    loc.clear (); pos temp;
    pos temp; temp.x = 1, temp.y = 1;
    temp.x = 1, temp.y = 1; loc.push_back(temp);
    loc.push_back(temp); temp.x = H, temp.y = W;
    temp.x = H, temp.y = W; loc.push_back(temp);
    loc.push_back(temp); 
     for (int i = 0; i <= R; i++)
    for (int i = 0; i <= R; i++) if ((1<<i) & x)
        if ((1<<i) & x) temp.x = forb[i].x, temp.y = forb[i].y, loc.push_back(temp);
            temp.x = forb[i].x, temp.y = forb[i].y, loc.push_back(temp);
 sort(loc.begin(), loc.end(), cmp);
    sort(loc.begin(), loc.end(), cmp);
 for (int i = 0; i + 1 < loc.size(); i++)
    for (int i = 0; i + 1 < loc.size(); i++) ret *= Calc(loc[i+1].x - loc[i].x, loc[i+1].y - loc[i].y), ret %= MOD;
        ret *= Calc(loc[i+1].x - loc[i].x, loc[i+1].y - loc[i].y), ret %= MOD;
 return ret;
    return ret; }
}
 int Count(int x)
int Count(int x)

 {
{ int ret = 1;
    int ret = 1; for (int i = 0; i < R; i++)
    for (int i = 0; i < R; i++) if (x & (1<<i))
        if (x & (1<<i)) ret = - ret;
            ret = - ret; return ret;
    return ret; }
}
 int main()
int main()

 {
{ freopen("in.txt", "r", stdin);
    freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);
    freopen("out.txt", "w", stdout); int T;
    int T; scanf("%d", &T);
    scanf("%d", &T);
 for (int i = 0; i < MOD; i++)
    for (int i = 0; i < MOD; i++) for (int j = 0; j <= i; j++)
        for (int j = 0; j <= i; j++)
 
         {
{ if (i == 0 || i == j) C[i][j] = 1;
            if (i == 0 || i == j) C[i][j] = 1; else
            else C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD; }
        }

 for (int ctr = 1; ctr <= T; ctr++)
    for (int ctr = 1; ctr <= T; ctr++)
 
     {
{
 scanf("%d%d%d", &H, &W, &R);
        scanf("%d%d%d", &H, &W, &R); for (int i = 0; i < R; i++)
        for (int i = 0; i < R; i++) scanf("%d%d", &forb[i].x, &forb[i].y);
            scanf("%d%d", &forb[i].x, &forb[i].y);
 LL ret = 0;
        LL ret = 0; for (int i = 0; i < (1<<R); i++)
        for (int i = 0; i < (1<<R); i++) ret += Count(i) * Solve(i), ret %= MOD;
            ret += Count(i) * Solve(i), ret %= MOD;
 ret += MOD;
        ret += MOD; ret %= MOD;
        ret %= MOD;

 printf("Case #%d: %I64d\n", ctr, ret);
        printf("Case #%d: %I64d\n", ctr, ret);
 }
    }
 return 0;
    return 0; }
} 
                    
                 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号