HDU 6333 Problem B. Harvest of Apples 莫队

Problem B. Harvest of Apples

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3221    Accepted Submission(s): 1248


 

Problem Description

There are n apples on a tree, numbered from 1 to n .
Count the number of ways to pick at most m apples.

 

Input

The first line of the input contains an integer T (1≤T≤105) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤105) .

 

Output

For each test case, print an integer representing the number of ways modulo 109+7 .

 

Sample Input

 

2 5 2 1000 500

 

Sample Output

 

16 924129523

 

Source

2018 Multi-University Training Contest 4

题意:

      求从n个苹果种取出最多m个的方法数。

做法:

       很神奇的居然是用莫队写的,就参考机房大神写了题解。  

       求S(n,m)=ΣC(n,i)(0<=i<=m)S(n,m)=ΣC(n,i)  (0<=i<=m)。 
可推出S(n,m)=S(n,m-1)+C(n,m),S(n,m)=2*S(n-1,m)-C(n-1,m),这样就可以用莫队了,转移是O(1),总复杂度O(T*sqrt(maxn))。


#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=200002;
const int mod=(int)1e9+7;
typedef long long ll;
int biao,n;
ll fac[maxn],inv[maxn],anss[maxn];
struct node{
    int n,k,id;
    node(){}
    node(int n,int k,int id):n(n),k(k),id(id){}
};
bool cmp(node a,node b){
    return a.n<b.n;
}
ll quick(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}
vector<node> ve[1005];
ll C(int n,int m){
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
    biao=sqrt(maxn);
    fac[0]=1;
    for(int i=1;i<=100000;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[100000]=quick(fac[100000],mod-2);
    for(int i=99999;~i;i--){
        inv[i]=inv[i+1]*(i+1)%mod;//反向线性求逆元
    }
    int nn,kk;

    int mma=-1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&nn,&kk);
        int aim=kk/biao;
        mma=max(mma,aim);
        ve[aim].push_back(node(nn,kk,i));
    }
    for(int i=0;i<=100000/biao;i++){
        if(!ve[i].size()) continue;
        sort(ve[i].begin(),ve[i].end(),cmp);
        ll l=ve[i][0].n,r=-1,res=0;
        for(int j=0;j<ve[i].size();j++){
            while(l<ve[i][j].n)
                res=(2*res+mod-C(l++,r))%mod;
            while(r<ve[i][j].k)
                res=(res+C(l,++r))%mod;
            while(r>ve[i][j].k)
                res=(res+mod-C(l,r--))%mod;
            anss[ve[i][j].id]=res;
        }
    }
    for(int i=1;i<=n;i++)
            printf("%lld\n",anss[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/81625856