sum「莫队」
在格尔巴乔夫新思维带领下数学题也可以用莫队了
觉得思路很棒,主要是莫队思想在数学题上应用
题目让求的是$\sum\limits_{i=0}^{i<=m} C_{n}^{m}$十万组询问,$n,m$范围十万
设$S_{n}^{m}=\sum\limits_{i=0}^{i<=m} C_{n}^{m}$,
根据定义$S_{n}^{m}=S_{n}^{m-1}+C_{n}^{m}$
又因为$C_{n}^{m}+C_{n}^{m-1}=C_{n+1}^{m}$
把上面柿子展开得到$S_{n}^{m}=2*S{n-1}^{m}-C(n-1,m)$
于是就可以愉快的莫队了
$S_{l}^{r}=2*S_{l}^{r-1}-C_{r-1}^{l}$
$S_{l}^{r}=S_{l-1}^{r}+C_{r,l}$
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1111111 const ll mod=1e9+7; ll id,q,n,m,l=1,r=0; ll ans=1,t; ll jie[A],ni[A],realans[A],belong[A]; struct node{ ll l,r,id; friend bool operator < (const node &a,const node &b){ return belong[a.l]==belong[b.l]?a.r<b.r:a.l<b.l; } }mo[A]; ll meng(ll x,ll k){ ll ans=1; for(;k;k>>=1,x=x*x%mod) if(k&1) ans=ans*x%mod; return ans; } ll C(ll x,ll y){ return jie[x]*ni[y]%mod*ni[x-y]%mod; } //s_n,m=2*s_n-1,m-C(n-1,m) //s_r,l=2*s_r-1,l-C(r-1,l) //s_r,l=s_r,l-1+C(r,l) //S_l,r=2*S_l,r-1-C(r-1,l) //S_l,r=S_l-1,r+C(r,l) int main(){ scanf("%lld",&id); scanf("%lld",&q); jie[0]=ni[0]=1; t=sqrt(100000); for(ll i=1;i<=100100;i++) jie[i]=jie[i-1]*i%mod,belong[i]=(i-1)/t+1; ni[100100]=meng(jie[100100],mod-2); for(ll i=100099;i>=1;i--) ni[i]=ni[i+1]*(i+1)%mod; for(ll i=1;i<=q;i++){ scanf("%lld%lld",&mo[i].r,&mo[i].l); mo[i].id=i; } sort(mo+1,mo+q+1); for(ll i=1;i<=q;i++){ while(l<mo[i].l) l++,ans=(ans+C(r,l))%mod; while(l>mo[i].l) ans=(ans-C(r,l)+mod)%mod,l--; while(r<mo[i].r) r++,ans=(2*ans-C(r-1,l)+mod)%mod; while(r>mo[i].r) ans=(((ans+C(r-1,l)))*meng(2,mod-2))%mod,r--; // printf("n=%lld m=%lld ans=%lld\n",mo[i].r,mo[i].l,ans); realans[mo[i].id]=ans; } for(ll i=1;i<=q;i++){ printf("%lld\n",realans[i]); } }
我已没有下降的余地