zoukankan      html  css  js  c++  java
  • 2018 Multi-University Training Contest 4

    莫队 + 组合数

    令f(n, m)表示从n个苹果中拿不超过m个的方法数。

    则 f(n, m) = f(n, m - 1) + C(n, m)

    则 f(n + 1, m) = f(n, m) + f(n, m - 1) = 2f(n, m) - C(n, m) (相当于第n+1个苹果不取的方法数+取的方法数)

    推导到此,可以发现f(n, m + 1), f(n, m - 1), f(n + 1, m), f(n - 1, m)可由f(n, m)用O(1)的时间推出。

    那么我们可以把(m, n)看成时间轴的两端,用莫队移动即可

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 100005;
    const int MOD = 1e9 + 7;
    int _, t;
    ll ans, res[N], fac[N], inv[N];
    struct Query{
        int n, m, id, block;
        bool operator < (const Query &rhs) const {
            return (block ^ rhs.block) ? m < rhs.m : (block ^ 1) ? n < rhs.n : n > rhs.n;
        }
    }query[N];
    
    void calc(){
        fac[0] = 1, fac[1] = 1, inv[0] = 1, inv[1] = 1;
        for(int i = 2; i <= N; i ++){
            fac[i] = (fac[i - 1] * i) % MOD;
            inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
        }
        for(int i = 1; i <= N; i ++){
            inv[i] = (inv[i] * inv[i - 1]) % MOD;
        }
        t = (int)sqrt(N);
    }
    
    ll C(int n, int m){
        return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    
    int main(){
    
        calc();
        _ = read();
        for(int i = 1; i <= _; i ++){
            query[i].n = read(), query[i].m = read();
            query[i].id = i, query[i].block = (query[i].m - 1) / t + 1;
        }
        sort(query + 1, query + _ + 1);
        int l = 1, r = 0;
        ans = 1;
        for(int i = 1; i <= _; i ++){
            int curL = query[i].m, curR = query[i].n;
            while(r < curR){
                r ++;
                ans = ((2 * ans - C(r - 1, l)) % MOD + MOD) % MOD;
            }
            while(l > curL){
                l --;
                ans = ((ans - C(r, l + 1)) % MOD + MOD) % MOD;
            }
            while(r > curR){
                ans = ((ans + C(r - 1, l)) % MOD * inv[2]) % MOD;
                r --;
            }
            while(l < curL){
                ans = (ans + C(r, l + 1)) % MOD;
                l ++;
            }
            res[query[i].id] = ans;
        }
        for(int i = 1; i <= _; i ++){
            printf("%lld
    ", res[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    ios -- 教你如何轻松学习Swift语法(一)
    collectionView,tableView的细节处理
    主流界面搭建原理(类似百思不得姐主界面)
    ios--时间格式化(cell业务逻辑处理)
    test
    Mac下安装Matlab R2015b
    最大奇约数
    编码问题
    最优二叉查找树
    二维数组和二级指针
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10907528.html
Copyright © 2011-2022 走看看