• 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
  • 相关阅读:
    【css】rem及其替换方案
    【css】如何实现环形进度条
    【js】我们需要无限滚动列表吗?
    【js】再谈移动端的模态框实现
    【js】callback时代的变更
    【js】为什么要使用react+redux
    【js】JavaScript parser实现浅析
    【css】回想下经典的布局
    【JS】温故知新: 从parseInt开始
    【渲染原理】浏览器渲染原理的个人整理
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5785594.html
Copyright © 2020-2023  润新知