A Simple Chess
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1057 Accepted Submission(s): 280
Problem Description
There is a
n×m
board, a chess want to go to the position
(n,m) from the position (1,1) .
The chess is able to go to position (x2,y2) from the position (x1,y1) , only and if only x1,y1,x2,y2 is satisfied that (x2−x1)2+(y2−y1)2=5, x2>x1, y2>y1 .
Unfortunately, there are some obstacles on the board. And the chess never can stay on the grid where has a obstacle.
I want you to tell me, There are how may ways the chess can achieve its goal.
(n,m) from the position (1,1) .
The chess is able to go to position (x2,y2) from the position (x1,y1) , only and if only x1,y1,x2,y2 is satisfied that (x2−x1)2+(y2−y1)2=5, x2>x1, y2>y1 .
Unfortunately, there are some obstacles on the board. And the chess never can stay on the grid where has a obstacle.
I want you to tell me, There are how may ways the chess can achieve its goal.
Input
The input consists of multiple test cases.
For each test case:
The first line is three integers, n,m,r,(1≤n,m≤1018,0≤r≤100) , denoting the height of the board, the weight of the board, and the number of the obstacles on the board.
Then follow r lines, each lines have two integers, x,y(1≤x≤n,1≤y≤m) , denoting the position of the obstacles. please note there aren't never a obstacles at position (1,1) .
For each test case:
The first line is three integers, n,m,r,(1≤n,m≤1018,0≤r≤100) , denoting the height of the board, the weight of the board, and the number of the obstacles on the board.
Then follow r lines, each lines have two integers, x,y(1≤x≤n,1≤y≤m) , denoting the position of the obstacles. please note there aren't never a obstacles at position (1,1) .
Output
For each test case,output a single line "Case #x: y", where x is the case number, starting from 1. And y is the answer after module
110119
.
Sample Input
1 1 0 3 3 0 4 4 1 2 1 4 4 1 3 2 7 10 2 1 2 7 1
Sample Output
Case #1: 1 Case #2: 0 Case #3: 2 Case #4: 1 Case #5: 5
Author
UESTC
Source
Recommend
题意:给你一个n*m的棋盘,求从(1,1)走到(n,m)有几种方法。再给你障碍的位置,障碍是不可以停留的。
思路:很明显,大部分的人都能想出用组合数求方法(慢慢化简),那么这道题剩下的问题就是障碍的处理方法和大组合数取模的方法。大组合数取模我们用lucas定理,其实赛后我补这道题才知道有这玩意。原理我也没深究,直接找别人模板套了。。那么剩下的问题就是障碍怎么处理,因为一条路可能会经过多个障碍,所以这里比较麻烦。我们可以这样,先求出从起点到各个障碍各有多少种方法(我们设变量为value)。然后我们对障碍点排序,距离起始点近的排在前面,然后用循环去枚举两两障碍点,j为i后面的点,假设第i个障碍能到达第j个障碍点,那么p[j].value-=起始点经过i点到达j点的方法数(也就是p[i].value*i点到j点的方法数)。每次处理完所有i后面的点我们再用总方法数(起始点到终点的方法数)-起始点经过i点到达终点的方法数(同上不解释了),这样就不会重复计算了。下面给代码。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<set>
using namespace std;
#define maxn 150000
#define MOD 110119
typedef long long LL;
LL n, m, fac[maxn];
int r;
struct node{
LL x, y, value;
}p[105];
LL quitmod(LL a, LL b)
{
LL tmp = a % MOD, ans = 1;
while (b)
{
if (b & 1) ans = ans * tmp % MOD;
tmp = tmp*tmp % MOD;
b >>= 1;
}
return ans;
}
LL C(LL n, LL m)
{
if (m>n)return 0;
return fac[n] * quitmod(fac[m] * fac[n - m], MOD - 2) % MOD;
}
LL cfun(LL n, LL m)
{
if (m == 0) return 1;
else return (C(n%MOD, m%MOD)*cfun(n / MOD, m / MOD)) % MOD;
}
bool jud(node a, node b){
if ((b.x + b.y - a.x - a.y) % 3 || 2 * (b.x - a.x) - (b.y - a.y)<0 || 2 * (b.y - a.y) - (b.x - a.x)<0)
return false;
return true;
}
bool cmp(node a, node b){
return a.x + a.y < b.x + b.y;
}
LL getvalue(node a, node b){
LL nn = (b.x + b.y - a.x - a.y) / 3;
LL mm = b.x - a.x - nn;
return a.value*cfun(nn, mm) % MOD;
}
int main(){
fac[0] = 1;
for (int i = 1; i < MOD; i++)
fac[i] = fac[i - 1] * i%MOD;
int tcase = 1;
while (scanf("%lld%lld%d", &n, &m, &r) != EOF){
int length = 1;
p[0].x = 1;
p[0].y = 1;
p[0].value = 1;
while (r--){
scanf("%lld%lld", &p[length].x, &p[length].y);
if (jud(p[0], p[length])){
p[length].value = getvalue(p[0], p[length]);
length++;
}
}
sort(p, p + length, cmp);
p[length].x = n;
p[length].y = m;
if (jud(p[0], p[length])){
p[length].value = getvalue(p[0], p[length]);
}
else{
printf("Case #%d: 0\n", tcase++);
continue;
}
for (int i = 1; i < length; i++){
for (int j = i + 1; j < length; j++){
if (jud(p[i], p[j])){
p[j].value -= getvalue(p[i], p[j]);
p[j].value = (p[j].value + MOD) % MOD;
}
}
if (jud(p[i], p[length])){
p[length].value -= getvalue(p[i], p[length]) % MOD;
p[length].value = (p[length].value + MOD) % MOD;
}
}
printf("Case #%d: %lld\n", tcase++, p[length].value);
}
}