HDU 5794 A Simple Chess Lucas大数组合数取模

来源:互联网 发布:淘宝延长收货如何设置 编辑:程序博客网 时间:2024/06/06 02:52

A Simple Chess

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


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 (x2x1)2+(y2y1)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,(1n,m1018,0r100), 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(1xn,1ym), 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 03 3 04 4 12 14 4 13 27 10 21 27 1
 

Sample Output
Case #1: 1Case #2: 0Case #3: 2Case #4: 1Case #5: 5
 
从起点(1,1)按日字形往终点(n,m)走,某些点有障碍不能走,问一共有多少种走法到达终点。
列一个二元一次方程,X代表需要走X个(1,2),Y代表需要走Y个(2,1),解出X与Y,C(x+y,x)代表总线路数。
因为n,m较大,需要用Lucas定理求大组合数取模。
然后R平方的复杂度解决容斥,对不能走的点排序,从前往后分析每一个障碍点影响的线路数目。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <set>#include <map>#include <stack>#include <cmath>#include <queue>#include <cstdio>#include <bitset>#include <string>#include <vector>#include <iomanip>#include <cstring>#include <iostream>#include <algorithm>#include <functional>#define maxn 100200#define LL long longusing namespace std;const LL p = 110119;LL quick_mod(LL a, LL b){        LL ans = 1;        a %= p;        while (b)        {                if (b & 1)                {                        ans = ans * a % p;                        b--;                }                b >>= 1;                a = a * a % p;        }        return ans;}LL num[p + 10];void init(){        num[0] = 1ll;        for (int i = 1; i <= p; i++)        {                num[i] = (num[i - 1] * i) % p;        }}LL C(LL n, LL m){        if (m > n)        {                return 0;        }        return (num[n] * quick_mod(num[m], p - 2) % p) * quick_mod(num[n - m], p - 2) % p;}LL Lucas(LL n, LL m){        if (m == 0)        {                return 1;        }        return C(n % p, m % p) * Lucas(n / p, m / p) % p;}LL dis(LL a, LL b, LL n, LL m){        if (a == n && b == m)        {                return 1;        }        if (n <= a || m <= b)        {                return 0;        }        if ((2 * n - m + b - 2 * a) % 3 != 0 || (2 * m - n + a - 2 * b) % 3 != 0)        {                return 0;        }        LL x = (2 * n - m + b - 2 * a) / 3;        LL y = (2 * m - n + a - 2 * b) / 3;        if (x < 0 || y < 0)        {                return 0;        }        LL sum = (m + n - a - b) / 3;        return Lucas(sum, min(x, y));}struct point{        LL x;        LL y;        friend bool operator < (point a, point b)        {                if (a.x == b.x)                {                        return a.y < b.y;                }                return a.x < b.x;        }};int main(){        LL n, m, r;        int tt = 1;        init();        while (scanf("%I64d %I64d %I64d", &n, &m, &r) != EOF)        {                LL ans = dis(1, 1, n, m);                point rs[110];                int flag=0;                for (int i = 0; i < r; i++)                {                        scanf("%I64d %I64d", &rs[i].x, &rs[i].y);                        if(rs[i].x==n&&rs[i].y==m)                        {                                flag=1;                                printf("Case #%d: 0\n", tt++);                                break;                        }                }                if(flag)                {                        continue;                }                sort(rs, rs + r);                LL tmp[110];                for (int i = 0; i < r; i++)                {                        tmp[i] = dis(1, 1, rs[i].x, rs[i].y);                        for (int j = 0; j < i; j++)                        {                                tmp[i] = (tmp[i] - tmp[j] * dis(rs[j].x, rs[j].y, rs[i].x, rs[i].y) % p + p) % p;                        }                        ans = (ans - tmp[i] * dis(rs[i].x, rs[i].y, n, m) % p + p) % p;                }                printf("Case #%d: %lld\n", tt++, ans);        }        return 0;}


0 0