zoukankan      html  css  js  c++  java
  • HDOJ:6333-Problem B. Harvest of Apples(组合数学+莫队算法+逆元)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6333

    解题心得:

    • 这个题可以说是十分精彩了,首先推组合数学的公式,其中一个很重要的公式是Cnm = Cmn-1 + Cm-1n-1  这个公式知道杨辉三角的都明白,但是一看发现似乎没啥用。但是可以以这个公式为基础继续推演下去。
    • 设Snm = Cn1 + Cn2 + Cn3 + ...... Cnm 然后继续使用上面的基本公式可以化成
    • Sn m-1 = Sn m - Cn m
      Sn m+1 = Sn m + Cn m+1
      Sn+1 m = 2Sn m - Cn m
      Sn m = (Sn+1 m + Cn m)/2
    • 这些个公式看起来没啥用,但是知道S的关系之间可以通过O(1)的复杂度来进行转化,这样就可以将105次询问离线化处理,也就是用莫队来维护。神奇阿,想破脑袋就是想不到阿。里面的除法取余的操作用逆元来处理,逆元可以先全与预处理出来。
    //
    //      ┏┛ ┻━━━━━┛ ┻┓
    //      ┃       ┃
    //      ┃   ━   ┃
    //      ┃ ┳┛   ┗┳ ┃
    //      ┃       ┃
    //      ┃   ┻   ┃
    //      ┃       ┃
    //      ┗━┓   ┏━━━┛
    //        ┃   ┃   神兽保佑
    //        ┃   ┃   代码无BUG!
    //        ┃   ┗━━━━━━━━━┓
    //        ┃           ┣┓
    //        ┃             ┏┛
    //        ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛
    //          ┃ ┫ ┫   ┃ ┫ ┫
    //          ┗━┻━┛   ┗━┻━┛
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+100;
    const int MOD = 1e9+7;
    typedef long long ll;
    
    struct Query {
        ll n, m, B, pos, ans;
    }q[maxn];
    
    ll unit, ans, fac[maxn], inv[maxn], t, rev2;
    
    ll quick_pow(ll a, ll b) {
        ll res = 1;
        while(b) {
            if(b&1)
                res = res * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return res;
    }
    
    void get_fac() { //预处理出阶乘和逆元
        fac[0] = 1;
        fac[1] =1;
        for(int i=2;i<maxn;i++) {
            fac[i] = i * fac[i-1] % MOD;
        }
    
        //神奇的操作
        inv[maxn-1] = quick_pow(fac[maxn-1], MOD-2);
        for(int i=maxn-2;i>=0;i--) {
            inv[i] = inv[i+1] * (i + 1) % MOD;
        }
    }
    
    bool cmp1(Query a, Query b) {
        if(a.B == b.B)
            return a.m < b.m;
        return a.B < b.B;
    }
    
    bool cmp2(Query a, Query b) {
        return a.pos < b.pos;
    }
    
    void init() {
        unit = sqrt(maxn);
        get_fac();
        scanf("%lld", &t);
        for(int i=0;i<t;i++) {
            scanf("%lld%lld", &q[i].n, &q[i].m);
            q[i].B = q[i].n/unit;
            q[i].pos = i;
        }
        rev2 = quick_pow(2, MOD-2);
        sort(q, q+t, cmp1);
    }
    
    ll C(ll n, ll m) {//得到c(n, m)的组合
        ll ans = fac[n] * inv[n-m] % MOD * inv[m] % MOD;
        return ans;
    }
    
    void addL(ll l, ll r) {
        ans = ((2 * ans % MOD) + MOD - C(l, r)) % MOD;
    }
    
    void cutL(ll l, ll r) {
        ans = (ans + C(l-1, r) % MOD) * rev2 % MOD;
    }
    
    void addR(ll l, ll r) {
        ans = (ans + C(l, r+1)) % MOD;
    }
    
    void cutR(ll l, ll r) {
        ans = (ans + MOD - C(l, r)) % MOD;
    }
    
    int main() {
        init();
        ll l=1, r = 1;
        ans = 2;
        for(int i=0;i<t;i++) {//离线莫队处理
            int L = q[i].n;
            int R = q[i].m;
            while(l < L) addL(l++, r);
            while(l > L) cutL(l--, r);
            while(r > R) cutR(l, r--);
            while(r < R) addR(l, r++);
    
            q[i].ans = ans;
         }
        sort(q, q+t, cmp2);
        for(int i=0;i<t;i++) {
            printf("%lld
    ",q[i].ans);
        }
        return 0;
    }
  • 相关阅读:
    C# 反射
    WinForm资源管理器开发(TreeView&ListView)
    枚举——完美立方
    关于考证
    人工智能时代,程序员要不要精通算法?
    程序员需要掌握哪些软技能?
    Android数据解析——JSON
    C# 数组转json
    jQuery跨域调用Web API
    oracle 创建表同时添加注释
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9463030.html
Copyright © 2011-2022 走看看