zoukankan      html  css  js  c++  java
  • 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
    ", t++, sum);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    教你一招Linux下文本比对方法
    Linux下find与exec的联手干大事
    Linux下Shell日期的格式,你知道几种?
    Linux下Python3.6的安装及避坑指南
    多线程中使用CompletableFuture
    ElasticSearch7.6.2中语法使用(更新中)
    ElasticSearch7.6.2使用_update_by_query语法
    ElasticSearch7.6.2使用_delete_by_query产生版本冲突问题
    filebeat7.6.2进程运行一段时间后自动退出问题解决
    把本地项目提交到gitLab
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5785594.html
Copyright © 2011-2022 走看看