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 (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).

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

题意:

走日字从(1,1)到(n,m)且不经过障碍的方案数;

思路:

原来向下和向右移动的方案数是C(n+m,m),这个是先把日字变成原来熟悉的走法,可以画个图研究一下,最后发现是(0,0)到(2*fy-fx/3,2*fx-fy/3)的方案数

不经过障碍可以用容斥加dp解决,dp[i]表示从起点到达第i个点中间不经过障碍点的方案数,那么dp[i]=起点到达i的总方案数-∑dp[j]*(j点到达i点的总方案数)

还有就是要预处理出阶乘,同时n和m都太大要用lucas定理化简,C(n,m)%mod=C(n/mod,m/mod)*C(n%mod,m%mod)%mod;

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=110119;
const int maxn=110;
LL n,m,x[maxn],y[maxn],dp[maxn],p[110130];
int r;
inline void init()
{
    p[0]=1;
    for(int i=1;i<=110119;i++)p[i]=p[i-1]*(LL)i%mod;
}
LL pow_mod(LL a,LL b)
{
    LL s=1,base=a;
    while(b)
    {
        if(b&1)s=s*base%mod;
        base=base*base%mod;
        b>>=1;
    }
    return s;
}
LL cal(LL a,LL b)
{
    if(a<mod&&b<mod)
    {
        if(b>a)return 0;
        return p[a]*pow_mod(p[b],mod-2)%mod*pow_mod(p[a-b],mod-2)%mod;
    }
    return cal(a/mod,b/mod)*cal(a%mod,b%mod)%mod;
}
LL solve(int L,int R)
{
    LL fx=x[R]-x[L],fy=y[R]-y[L];
    if((2*fy-fx)%3||(2*fx-fy)%3||2*fy<fx||2*fx<fy)return 0;
    LL up=(2*fy-fx)/3,down=(fx+fy)/3;
    return cal(down,up);
}
int main()
{
    init();
    int Case=0;
    while(scanf("%lld%lld%d",&n,&m,&r)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        int flag=0;
        x[0]=1,y[0]=1;
        for(int i=1;i<=r;i++)
        {
            scanf("%lld%lld",&x[i],&y[i]);
            if(x[i]==n&&y[i]==m)flag=1;
        }
        LL ans=0;
        if(!flag)
        {
            x[0]=1,y[0]=1;
            dp[0]=1;
            x[++r]=n,y[r]=m;
            for(int i=1;i<=r;i++)
            {
                for(int j=1;j<=i;j++)
                {
                    if(x[j]>=x[i]&&y[j]>=y[i])swap(x[i],x[j]),swap(y[i],y[j]);
                }
            }
            for(int i=1;i<=r;i++)dp[i]=solve(0,i);
            for(int i=1;i<=r;i++)
            {
                for(int j=1;j<i;j++)
                {
                    if(x[j]<=x[i]&&y[j]<=y[i])dp[i]=(dp[i]-dp[j]*solve(j,i)%mod+mod)%mod;
                }
            }
            for(int i=1;i<=r;i++)if(x[i]==n&&y[i]==m)ans=dp[i];
        }
        printf("Case #%d: %lld\n",++Case,ans);
    }
    return 0;
}

  

时间: 2024-10-12 20:13:08

hdu-5794 A Simple Chess(容斥+lucas+dp)的相关文章

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

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)

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

HDU 5794 A Simple Chess (Lucas + dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794 多校这题转化一下模型跟cf560E基本一样,可以先做cf上的这个题. 题目让你求一个棋子开始在(1,1),只能像马一样走且往右下方走,不经过坏点,有多少种走法能到达(n,m)点. 比如n=6, m=5 有两个坏点,模型转换 如下图: 转换成简单模型之后,只要把棋子可能经过的坏点存到结构体中,按照x与y从小到大排序. dp[i]表示从起点到第i个坏点且不经过其他坏点的方案数. dp[i] = L

HDU 5794 A Simple Chess

可以用总方案数减去经过障碍物的方案数. 先写一个判断某点是否可达的函数~ check(a,b) 再写一个某点到某点的方案数的函数~ cal(x1,x2,y1,y2) 设随便走 从(1,1)到(n,m)的方案数为P 设从(1,1)走到第i个障碍物并且不经过其余障碍物的方案数为num[i]. 那么 answer = P - sum{ num[i] * cal(x[i],y[i],n,m) }. 计算num[i] 可以将所有的障碍物按照x从小到大排个序,然后o(r*r)效率得到. #pragma co

HDU 4971 A simple brute force problem.(dp)

HDU 4971 A simple brute force problem. 题目链接 官方题解写的正解是最大闭合权,但是比赛的时候用状态压缩的dp也过掉了- -,还跑得挺快 思路:先利用dfs预处理出每个项目要完成的技术集合,那么dp[i][j]表示第i个项目,已经完成了j集合的技术,由于j这维很大,所以利用map去开数组 代码: #include <cstdio> #include <cstring> #include <algorithm> #include &l

HDU - 4971 A simple brute force problem. (DP)

Problem Description There's a company with several projects to be done. Finish a project will get you profits. However, there are some technical problems for some specific projects. To solve the problem, the manager will train his employee which may

HDU 6053 TrickGCD 莫比乌斯函数/容斥/筛法

题意:给出n个数$a[i]$,每个数可以变成不大于它的数,现问所有数的gcd大于1的方案数.其中$(n,a[i]<=1e5)$ 思路:鉴于a[i]不大,可以想到枚举gcd的值.考虑一个$gcd(a_1,a_2,a_3…a_n)=d$,显然每个$a_i$的倍数都满足,有$\frac{a_i}{d}$种方案 那么一个d对答案的贡献为\[\prod_{i=1}^{min(a)}{\lfloor\frac{a_i}{d}\rfloor}    \] 但是所有的d计入会有重复情况,考虑容斥,对d进行素数分