HDU - 6333 Harvest of Apples(组合数+莫队)

原题链接

题意:

一颗苹果树上有 $n$ 个苹果, 编号从 $1...n$ ,问最多取 $m$ 个苹果有多少种取法。

思路:

就是求       但是 $T, n ,m$ 均是 $1e5$ 的范围,直接求肯定爆炸,但此题只有查询,我们就可以用莫队来做,离线查询从而减少复杂度;

以上性质可推导求得,然后我们就可以用莫队进行状态的转移;

  1 /*
  2 * @Author: windystreet
  3 * @Date:   2018-08-03 14:45:03
  4 * @Last Modified by:   windystreet
  5 * @Last Modified time: 2018-08-03 16:42:19
  6 */
  7 #include<bits/stdc++.h>
  8 
  9 using namespace std;
 10 
 11 #define X first
 12 #define Y second
 13 #define eps  1e-2
 14 #define gcd __gcd
 15 #define pb push_back
 16 #define PI acos(-1.0)
 17 #define lowbit(x) (x)&(-x)
 18 #define bug printf("!!!!!\n");
 19 #define mem(x,y) memset(x,y,sizeof(x))
 20 
 21 typedef long long LL;
 22 typedef long double LD;
 23 typedef pair<int,int> pii;
 24 typedef unsigned long long uLL;
 25 
 26 const int maxn = 1e5+2;
 27 const int INF  = 1<<30;
 28 const int mod  = 1e9+7;
 29 
 30 struct node
 31 {
 32     LL n,m,id;
 33 }s[maxn];
 34 LL ans[maxn],inv[maxn],fact[maxn];
 35 LL sq,tot;
 36 bool cmp(node a, node b){
 37     if(a.n/sq == b.n/sq) return a.m < b.m;
 38     return a.n/sq <b.n/sq;
 39 }
 40 LL qpow(LL x,LL y){
 41     LL res = 1;
 42     while(y){
 43         if(y&1)res = (LL)res*x*1ll%mod;
 44         x = x * x % mod;
 45         y >>= 1;
 46     }
 47     return res; 
 48 }
 49 void init(){
 50     fact[0] = 1;
 51     for(int i = 1;i < maxn;i++){
 52         fact[i] = fact[i-1]*i%mod;             // 预处理阶乘 
 53     }
 54     inv[maxn-1] = qpow(fact[maxn-1],mod-2);    // 预处理逆元
 55     for(int i=maxn-2;i>=0;i--){
 56         inv[i] = inv[i+1]*(i+1)%mod;
 57     }
 58 }
 59 
 60 LL C(LL n,LL m){                               // 组合数
 61     return (fact[n] * inv[m] %mod) * inv[n-m] % mod;
 62 }
 63 
 64 void solve(){
 65     int t; tot = 0;
 66     init();
 67     scanf("%d",&t);
 68     for(int i=1;i<=t;i++){
 69         scanf("%lld%lld",&s[i].n,&s[i].m);
 70         s[i].id = i; tot = max(tot,s[i].n); 
 71     }
 72     sq = sqrt(tot);
 73     sort(s+1,s+1+t,cmp);
 74     LL L=1,R=-1,res = 0;
 75     for(int i=1;i<=t;i++){                      // 莫队部分,每次进行状态转移
 76         while(L<s[i].n){res = ((2*res - C(L++,R))+mod)%mod;}
 77         while(L>s[i].n){res = ((res + C(--L,R))%mod*inv[2]%mod)%mod;}
 78         while(R<s[i].m){res = (res + C(L,++R))%mod;}
 79         while(R>s[i].m){res = (res - C(L,R--)+mod)%mod;}
 80         ans[s[i].id ] = res;
 81     }
 82     for(int i=1;i<=t;i++){
 83         printf("%lld\n",ans[i]);
 84     }
 85     return;
 86 }
 87 
 88 int main()
 89 {
 90 //    freopen("in.txt","r",stdin);
 91 //    freopen("out.txt","w",stdout);
 92 //    ios::sync_with_stdio(false);
 93     int t = 1;
 94     //scanf("%d",&t);
 95     while(t--){
 96     //    printf("Case %d: ",cas++);
 97         solve();
 98     }
 99     return 0;
100 }

比赛时没有做出来,真的蒟蒻

 

 

 

 

posted @ 2018-08-03 17:13  windystreet  阅读(135)  评论(0编辑  收藏  举报