A Simple Chess---hdu5794(容斥+Lucas)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5794

题意:给你一个n*m的网格,问从(1, 1)走到(n, m)的方案数是多少,其中有r个点是不可到达的;

根据公式我们可以知道每次只能走”日"型;

路径如上图所示,我们可以看到有很多点是不可达的,可达点都是满足(x+y)%3=2的;路径可以看成一个斜着放置的杨辉三角。我们只需要把坐标转换一下即可,这是没有障碍时的方案数;

让(1,1)到(n,m)中如果有一个障碍,那么我们可以用起点到终点的方法数-起点到障碍点的方法数*障碍点到终点的方法数;同样如果有 r 个,那就减去r次这样的情况;

同样处理到达每个点的时候也是这样处理的;

注意有不可达的,所以判断一下不然会re的;

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<math.h>
using namespace std;
#define N 120000
#define PI 4*atan(1.0)
#define mod 110119
#define met(a, b) memset(a, b, sizeof(a))
typedef long long LL;

struct node
{
    LL x, y;
    friend bool operator < (node p, node q)
    {
        if(p.x!=q.x)
            return p.x < q.x;
        return p.y < q.y;
    }
}a[105];

LL f[N] = {1};

LL Pow(LL a, LL b)
{
    LL ans = 1;
    while(b)
    {
        if(b&1)
            ans = ans*a%mod;
        b/=2;
        a = a*a%mod;
    }
    return ans%mod;
}

LL C(LL n, LL m)
{
    if(m>n)return 0;
    if(m == 0)return 1;
    LL ans = f[n] * Pow(f[m], mod-2)%mod * Pow(f[n-m], mod-2) % mod;
    return ans;
}
LL Lucas(LL n, LL m)
{
    if(n<0 || m<0)return 0;///会出现不可达的情况,所以注意判断,否则会re;
    if(m > n) return 0;
    if(m == 0) return 1;
    return C(n%mod, m%mod) * Lucas(n/mod, m/mod) % mod;
}

LL solve(LL x1, LL y1, LL x2, LL y2)
{
    if((x1+y1)%3 != 2)return 0;
    if((x2+y2)%3 != 2)return 0;

    LL ax = (x1+y1-2)/3;
    LL ay = y1 - 1 - ax;

    LL bx = (x2+y2-2)/3;
    LL by = y2 - 1 - bx;

    return Lucas(bx-ax, by-ay);
}

int main()
{
    for(int i=1; i<=110119; i++)
        f[i] = f[i-1]*i % mod;

    LL n, m;
    int t = 1, r;
    while(scanf("%I64d %I64d %d", &n, &m, &r)!=EOF)
    {
        LL ans[N];///起点到i的方案数;

        for(int i=1; i<=r; i++)
            scanf("%I64d %I64d", &a[i].x, &a[i].y);

        sort(a+1, a+r+1);///按x的升序排列,再按y的升序排列;

        LL sum = solve(1, 1, n, m);

        for(int i=1; i<=r; i++)
        {
            ans[i] = solve(1, 1, a[i].x, a[i].y);
            for(int j=1; j<i; j++)
            {
                ans[i] = ((ans[i] - ans[j]*solve(a[j].x, a[j].y, a[i].x, a[i].y)%mod) + mod) % mod;
            }
        }
        for(int i=1; i<=r; i++)
        {
            sum = (sum - ans[i]*solve(a[i].x, a[i].y, n, m)%mod + mod) % mod;
        }
        printf("Case #%d: %I64d\n", t++, sum);
    }
    return 0;
}

时间: 2024-10-24 16:06:44

A Simple Chess---hdu5794(容斥+Lucas)的相关文章

hdu5794 A Simple Chess 容斥+Lucas 从(1,1)开始出发,每一步从(x1,y1)到达(x2,y2)满足(x2?x1)^2+(y2?y1)^2=5, x2&gt;x1,y2&gt;y1; 其实就是走日字。而且是往(n,m)方向走的日字。还有r个障碍物,障碍物不可以到达。求(1,1)到(n,m)的路径条数。

A Simple Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2597    Accepted Submission(s): 691 Problem Description There is a n×m board, a chess want to go to the position (n,m) from the pos

hdu-5794 A Simple Chess(容斥+lucas+dp)

题目链接: 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 (

HDU5794 A Simple Chess 容斥+lucas

分析:转自http://blog.csdn.net/mengzhengnan/article/details/47031777 一点感想:其实这个题应该是可以想到的,但是赛场上并不会 dp[i]的定义很巧妙,容斥的思路也非常清晰 然后就是讨论lucas的用法,首先成立的条件是mod是素数 但是如果这个题mod很大,组合数取模感觉就不太可做了 我认为当mod很大时,n应该很小可以预处理,但是n很大时mod应该比较小,这样也可以预处理 如果n和mod都很大我就不会了.... 这个题在预处理的时候,同

hdu_5794_A Simple Chess(lucas+dp)

题目链接:hdu_5794_A Simple Chess 题意: 给你n,m,从(1,1)到(n,m),每次只能从左上到右下走日字路线,有k(<=100)的不能走的位置,问你有多少方案 题解: 画图可看到路线是一个杨辉三角的图,然后我们可以将对应的x,y转换到对应的点上,也可以吧杨辉三角看成一个平行四边形, 我这里看成的平行四边形,设dp[i]为从起点到第i个障碍物的的方案数,那么dp[i]=dp[i]-sum(dp[j](第j个点能走到i这个点)*(j到i的方案数)). 然后我们把终点放到最后

HDU 5794 A Simple Chess(杨辉三角+容斥原理+Lucas)

题目链接 A Simple Chess 打表发现这其实是一个杨辉三角…… 然后发现很多格子上方案数都是0 对于那写可能可以到达的点(先不考虑障碍点),我们先叫做有效的点 对于那些障碍,如果不在有效点上,则自动忽略 障碍$(A, B)$如果有效,那么就要进行如下操作: 以这个点为一个新的杨辉三角的顶点,算出目标点的坐标$(x, y)$. 目标点的答案减去$C(A, B) * C(x, y)$的值. 但是这样会造成重复计算,原因是障碍之间可能有相互影响的关系. 这个时候就要考虑容斥原理,DFS消除这

HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)

传送门 A Simple Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 667    Accepted Submission(s): 168 Problem Description There is a n×m board, a chess want to go to the position (n,m) from the

cf451E Devu and Flowers 卢卡斯定理+容斥定理

题目:http://codeforces.com/problemset/problem/451/E 题意:有n个盒子(n<=20),每个盒子中有10^12个小球,现从每个盒子中取出若干球(可为0),求共取出s个小球(s<=10^14)的方案数. 组合数学问题,求C(n,m).但n,m过大时,可用卢卡斯定理. 卢卡斯定理:C(n,m) %p = C(n/p,m/p) * C(n%p,m%p) 从n个盒子中取出s个球的方案数,相当于插板,即 C(s+n-1,n-1).注意这是没有限制条件的情况.

HDU 6397(2018多校第8场1001) Character Encoding 容斥

听了杜教的直播后知道了怎么做,有两种方法,一种构造函数(现在太菜了,听不懂,以后再补),一种容斥原理. 知识补充1:若x1,x2,.....xn均大于等于0,则x1+x2+...+xn=k的方案数是C(k+m-1,m-1)种(貌似紫书上有,记不太清了). 知识补充2:若限制条件为n(即x1,x2....xn均小于n,假设有c个违反,则把k减掉c个n(相当于把c个超过n的数也变成大于等于0的),就可以套用知识1的公式了. 则最后的答案为sum( (-1)^c * C(m , c) * C(m-1+

Luogu4640 BJWC2008 王之财宝 容斥、卢卡斯定理

传送门 题意:有$N$种物品,其中$T$个物品有限定数量$B_i$,其他则没有限定.问从中取出不超过$M$个物品的方案数,对质数$P$取模.$N,M \leq 10^9 , T \leq 15 , P \leq 10^5$ 在$N$种物品中选出不超过$M$中物品的方案数可以用插板法(插板法只能满足刚好$M$个,那么我们可以虚构出一个数量无限的物品,把剩下的没选择完的都丢给它,这样插板法就能做了) 发现$T$很小,直接容斥即可 $N,M \leq 10^9$不能直接预处理,考虑到$P$为质数且范围