zoukankan      html  css  js  c++  java
  • 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 (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 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
    ",++Case,ans);
        }
        return 0;
    }
    

      

     
  • 相关阅读:
    [其他]将Windows Terminal添加到右键菜单
    [VS Code]在自己的Ubuntu服务器上构建VSCode Online
    [Go]goFileView-基于Golang的在线Office全家桶预览
    [Go]基于Go语言的Web路由转发,多个网站共享一个端口(新版本,支持WebSocket)
    [WSL]在Windows10子系统里安装运行桌面(xUbuntu)
    [Go]使用Golang对鸢尾花数据集进行k-means聚类
    [Python+JavaScript]JS调用摄像头并拍照,上传至tornado后端并转换为PIL的Image
    [Python]Python基于OpenCV批量提取视频中的人脸并保存
    [WSL]Windows10 Ubuntu子系统编译安装线程安全版LAMP
    [Go]基于Go语言的Web路由转发,多个网站共享一个端口(存在问题,已经抛弃,新解决方案请看新博客)
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/6286327.html
Copyright © 2011-2022 走看看