• HDU5794


    HDU5794 - A Simple Chess


    做法:首先的想法就是用总方案数减去,经过过障碍的方案数A。第一个思路就是容斥,但是显然不符合数据规模。另一个思路就是将障碍物从左上到右下排序,dp[i] 表示不经过前i-1个障碍,到达第i个障碍的方案数。这里定义cal(a,b) 表示从a到b,无障碍情况下的方案数,a[i]是排序后的第i个点,起点st,终点ed,pre(a)表示能到达a的点集。那么 (A = sum_{i=1}^n dp[i]*cal(a[i],ed)),现在考虑转移,dp[i] 就是 到达pre(a[i])中每个点的不经过任何障碍的方案数的和,而这个值与答案类似可以通过用总方案减去,之前经过过障碍的方案数,这些dp值已经求出来了,直接转移即可。cal(a,b) 中需要注意组合数的计算过程。lucas实现的时候没有判n和m的正负,RE了很长一段时间。。

    #include <cstdio>
    #include <algorithm>
    typedef long long ll;
    const int mod = 110119;
    using namespace std;
    ll n, m, dp[111], tmp, ans;
    int r;
    ll f[mod], rv[mod];
    ll C(ll n, ll m) {
        return n < m ? 0: f[n]*rv[n-m]%mod*rv[m]%mod;
    }
    ll lucas(ll n, ll m) {
        if(n<m || n < 0 || m < 0) return 0;
        ll ans=1;
        for(; m; n/=mod, m/=mod) ans = ans*C(n%mod, m%mod)%mod;
        return ans;
    }
    struct node {
        ll x, y;
        node(){}
        node(ll _x, ll _y) {
            x = _x; y = _y;
        }
    }a[111];
    bool cmp(node a,node b) {
        return (a.x + a.y) <= (b.x + b.y);
    }
    int inb(node a) {
        if(a.x < 1 || a.x > n || a.y < 1 || a.y > m) return 0;
        return 1;
    }
    node pre1(node a) {
        return node(a.x-2LL,a.y-1LL);
    }
    node pre2(node a) {
        return node(a.x-1LL,a.y-2LL);
    }
    ll cal(node a, node b) {
        if( !inb(a) || !inb(b) ) return 0;
        ll x = b.x - a.x + 1, y = b.y - a.y + 1;
        if(x == 1 && y == 1) return 1;
        if( !inb(node(x,y)) ) return 0;
        if(x + y - 2 < 0) return 0;
        if( (x+y-2)%3 ) return 0;
    
        ll k = (x+y-2)/3LL;
        ll num = x-k-1;
    
        return lucas(k, num);
    }
    int main() {
        rv[0] = rv[1] = f[0] = f[1] = 1;
        for(int i = 2; i < mod; ++i) {
            f[i] = f[i-1]*i % mod; rv[i] = -rv[mod%i]*(mod/i)%mod;
            while(rv[i] < 0) rv[i] += mod;
        }
        for(int i = 2; i < mod; ++i) rv[i] = rv[i]*rv[i-1]%mod;
        int C = 0;
        while(scanf("%lld %lld %d", &n, &m, &r) != EOF) {
            for(int i = 1; i <= r; ++i) scanf("%lld %lld", &a[i].x, &a[i].y);
            sort(a+1, a+1+r, cmp);
            ans = cal(node(1,1), node(n,m));
            for(int i = 1; i <= r; ++i) {
                dp[i] = tmp = 0;
                for(int j = 1; j < i; ++j) {
                    tmp += dp[j]*cal(a[j],pre1(a[i]))%mod;
                    tmp += dp[j]*cal(a[j],pre2(a[i]))%mod;
                    tmp %= mod;
                }
                dp[i] = cal(node(1,1), pre1(a[i]))%mod + cal(node(1,1), pre2(a[i]))%mod - tmp;
                ((dp[i]%=mod) += mod)%=mod;
                ans -= dp[i]*cal(a[i],node(n,m))%mod;
                ((ans%=mod) += mod)%=mod;
            }
            printf("Case #%d: %lld
    ",++C,ans);
        }
    	return 0;
    }
    
    
  • 相关阅读:
    ArrayList源码剖析
    Java集合框架
    Java数据结构和算法(十五)——无权无向图
    Java数据结构和算法(十四)——堆
    Java数据结构和算法(十三)——哈希表
    Java数据结构和算法(十二)——2-3-4树
    Java数据结构和算法(十一)——红黑树
    Java数据结构和算法(十)——二叉树
    Java数据结构和算法(九)——高级排序
    [刷题] Leetcode算法 (2020-2-27)
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/9853829.html
Copyright © 2020-2023  润新知