题意:
一颗苹果树上有 $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("!!!!! "); 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 ",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 }
比赛时没有做出来,真的蒟蒻