6333 Harvest of Apples (莫隊)
阿新 • • 發佈:2018-12-18
題意:給你T組詢問,每組詢問有兩個值n,m,讓你輸出C(n,0)+C(n,1)+...+C(n,m-1)+C(n,m)的值。(1<=T,n,m<=1e5)
由於T的值太大,所以直接算會超時。
考慮莫隊演算法:
首先要有個預備知識:
這樣,知道S(n,m-1)的值,就能在O(1)的時間算出S(n,m)的值了。可以按照m的大小分塊,把m,n作為左右下標,來回跳就行了。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; const int SQRTN=sqrt(N)+10; const ll mod=1e9+7.5; int in[N]; ll ans[N],fact[N],inv[N],invfact[N]; struct query { int i; ll n,m; bool operator<(const query& b) { return in[m]==in[b.m]?(in[m]&1?n>b.n:n<b.n):m<b.m; } } qr[N]; void init() { inv[1]=fact[0]=invfact[0]=1; for(int i=2; i<N; ++i)inv[i]=(mod-mod/i)*inv[mod%i]%mod; for(int i=1; i<N; ++i) { fact[i]=fact[i-1]*i%mod; invfact[i]=invfact[i-1]*inv[i]%mod; } } ll C(ll n,ll m) { return n<m?0:fact[n]*invfact[m]%mod*invfact[n-m]%mod; } int main() { init(); int T; scanf("%d",&T); for(int i=0; i<T; ++i) { scanf("%lld%lld",&qr[i].n,&qr[i].m); qr[i].i=i; in[i]=i/SQRTN; } sort(qr,qr+T); ll m=0,n=1,sum=1; for(int i=0; i<T; ++i) { while(m<qr[i].m)++m,sum=(sum+C(n,m))%mod; while(m>qr[i].m)sum=(sum-C(n,m))%mod,--m; while(n<qr[i].n)++n,sum=(sum*2-C(n-1,m))%mod; while(n>qr[i].n)sum=(sum+C(n-1,m))*inv[2]%mod,--n; ans[qr[i].i]=(sum+mod)%mod; } for(int i=0; i<T; ++i)printf("%lld\n",ans[i]); return 0; }