HDU6333 莫队+组合数学

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6333

题意:

T次询问,每次询问n个苹果中最多拿m个苹果的方法数

题解:

因为T为1e5,所以直接做时间复杂度会很高,所以我们因为每次询问可以离线下来,我们考虑莫队算法

首先这个题可以看作求

[sum_{i=0}^mC_n^i\ 令S(n,m)为sum_{i=0}^mC_n^i\ 可以得到公式\ S(n,m)=S(n,m-1)+C_n^m\ S(n,m)=S(n,m=1)-C_n^m+1\ S(n,m)=2*S(n-1,m)-C_{n-1}^m\ S(n,m)=frac{S(n+1,m)+C_n^m}{2} ]

根据这个公式我们就可以用莫队

[Tsqrt {len}就过了 ]

代码:

/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */
// warm heart, wagging tail,and a smile just for you!
//
//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                           O  =  /O
//                        ____/`---'\____
//                      .'  |     |//  `.
//                     /  |||  :  |||//  
//                    /  _||||| -:- |||||-  
//                    |   | \  -  /// |   |
//                    | \_|  ''---/''  |   |
//                      .-\__  `-`  ___/-. /
//                  ___`. .'  /--.--  `. . __
//               ."" '<  `.___\_<|>_/___.'  >'"".
//              | | :  `- \`.;` _ /`;.`/ - ` : | |
//                 `-.   \_ __ /__ _/   .-` /  /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//                     佛祖保佑      永无BUG
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********
")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
"

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct node {
    int l, r, id;
} q[maxn];
int pos[maxn];
bool cmp(node a, node b) {
    if(pos[a. l] == pos[b.l]) return a.r < b.r;
    return pos[a.l] < pos[b.l];
}

LL Ans;
LL f[maxn], inv[maxn];
LL qpow(LL a, LL b) {
    LL Ans = 1;
    while (b) {
        if (b & 1) Ans = (Ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return Ans;
}
void init() {
    f[1] = 1;
    for (int i = 2; i < maxn; i++) f[i] = (f[i - 1] * i) % mod;
    inv[maxn - 1] = qpow(f[maxn - 1], mod - 2);
    for (int i = maxn - 2; i >= 1; i--) inv[i] = (inv[i + 1] * (i + 1)) % mod;
}
LL C(int n, int m) {
    if (n < 0 || m < 0 || m > n) return 0;
    if (m == 0 || m == n) return 1;
    return f[n] * inv[n - m] % mod * inv[m] % mod;
}

LL ans[maxn];
int main() {
#ifndef ONLINE_JUDGE
    FIN
#endif
    init();
    int n;
    scanf("%d", &n);
    int sz = sqrt(n);
    for(int i = 1; i <= n; i++) {
        pos[i] = i / sz;
        scanf("%d%d", &q[i].l, &q[i].r);
        q[i].id = i;
    }
    sort(q + 1, q + n + 1, cmp);
    int l = 1, r = 0;
    Ans = 1;
    for(int i = 1; i <= n; i++) {
        while(l < q[i].l) {
            Ans = Ans * 2 % mod - C(l, r);
            if (Ans < 0) Ans += mod;
            l++;
        }
        while(l > q[i].l) {
            l--;
            Ans = (Ans + C(l, r)) % mod * inv[2] % mod;
        }
        while(r < q[i].r) {
            r++;
            Ans = (Ans + C(l, r)) % mod;
        }
        while(r > q[i].r) {
            Ans = (Ans - C(l, r) + mod) % mod;
            r--;
        }
        ans[q[i].id] = Ans;
    }
    for(int i = 1; i <= n; i++) {
        printf("%lld
", ans[i]);
    }
    return 0;
}
每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
原文地址:https://www.cnblogs.com/buerdepepeqi/p/10878447.html