zoukankan      html  css  js  c++  java
  • hdu6333 /// 莫队+组合数

    题目大意:

    给定n m

    在n个数中最多选择m个的所有方案

    题解:https://blog.csdn.net/qq_36300700/article/details/81385244

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    const int mod=1e9+7;
    const int N=1e5+5;
    
    /********组合数模板*********/
    LL pow_mod(LL a, LL b) {
        LL res = 1LL; a %= mod;
        while(b){
            if(b & 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        } return res;
    }
    LL inv(LL a) { return pow_mod(a, mod-2); }
    LL F[N], Finv[N];//F是阶乘,Finv是逆元的阶乘
    void init() {
        F[0] = Finv[0] = 1LL;
        for(int i = 1; i < N; i ++){
            F[i] = F[i-1] * 1LL * (LL)i % mod;
            Finv[i] = Finv[i-1] * 1LL * inv(i) % mod;
        }
    } // O(n)预处理
    LL C(LL n, LL m) {
        if(m < 0 || m > n) return 0;
        return F[n] * 1LL * Finv[n - m] % mod * Finv[m] % mod;
    } // O(1)获得组合数C(n,m)
    /**************************/
    
    LL res[N];
    
    /********莫队*********/
    int len;
    struct Q {
        LL n,m;
        int block, id;
        bool operator <(const Q& q)const {
            if(block==q.block) return n<q.n;
            return block<q.block;
        }
    }q[N];
    void Mo() { 
        LL L=0, R=0, ans=1LL;
        for(int i=0;i<t;i++) {
            LL l=q[i].n, r=q[i].m;
            while(L>l) ans=((ans+C(L-1LL,R))%mod*Finv[2])%mod, L--;
            while(L<l) ans=(2*ans%mod-C(L,R)+mod)%mod, L++;
            while(R<r) ans=(ans+C(L,R+1))%mod, R++;
            while(R>r) ans=(ans-C(L,R)+mod)%mod, R--;
            res[q[i].id]=ans;
        }
    }
    /**************************/
    
    int main()
    {
        init(); len=sqrt(N);
        int t; scanf("%d",&t);
        for(int i=0;i<t;i++) {
            scanf("%lld%lld",&q[i].n,&q[i].m);
            q[i].block=q[i].m/len; q[i].id=i;
        }
        sort(q,q+t);
        Mo();
        for(int i=0;i<t;i++)
            printf("%lld
    ",res[i]);
    
        return 0;
    }
    View Code

    莫队模板

    int len;
    struct Q {
        LL l,r;
        int block, id;
        bool operator <(const Q& q)const {
            if(block==q.block) return n<q.n;
            return block<q.block;
        }
    }q[N];
    void Mo() { 
        len=sqrt(N);
        sort(q,q+t);
        LL L=0, R=0, ans= ;
        for(int i=0;i<t;i++) {
            LL l=q[i].l, r=q[i].r;
            while(L>l) --L, ans= ;
            while(L<l) L++, ans= ; 
            while(R>r) R--, ans= ;
            while(R<r) ++R, ans= ;
            res[q[i].id]=ans;
        }
    }
    View Code
  • 相关阅读:
    小X的密码破译
    小X的加法难题
    足球联赛
    机器分配
    化装晚会
    Soundex编码
    迷之阶梯
    使用JMeter做压力测试
    SCOI 2010 序列操作
    动态求区间K大值(权值线段树)
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10322487.html
Copyright © 2011-2022 走看看