题面戳这里
思路:
noip考莫队???!!!
考场上死活没往这方面想啊!!!数据分治忘写endl50pts滚粗了
这里每个询问都有n,m两个参数
我们可以把它看做常规莫队中的l和r
然后利用组合数的可递推性质就好了
相信改变m大家都会写,n呢?
看图:
我们发现,$S_n^m = S_{n-1}^m \times 2 - C_n^{m+1} + C_{n-1}^{m+1}$
(因为杨辉三角的性质)
所以n也可以递推
套个莫队就好了
代码:
#include<iostream> #include<cstdio> #include<algorithm> #define rii register int i #define rij register int j #define int long long const int p=1e9+7; using namespace std; struct que{ int n,m,ans,bh; }x[100005]; int ny[100005],jc[100005],jcny[100005],q,sy[100005],nn,nm,ans; void qny() { ny[1]=1; ny[0]=1; for(rii=2;i<=100000;i++) { ny[i]=(p-p/i)*ny[p%i]%p; } } void jic() { jcny[0]=1; jc[1]=1; jcny[1]=1; for(rii=2;i<=100000;i++) { jc[i]=jc[i-1]*i; jc[i]%=p; jcny[i]=jcny[i-1]*ny[i]; jcny[i]%=p; } } void ycl() { qny(); jic(); } bool cmp1(que lk,que kl) { if(sy[lk.n]==sy[kl.n]) { return lk.m<kl.m; } return lk.n<kl.n; } bool cmp2(que lk,que kl) { return lk.bh<kl.bh; } int c(int n,int m) { int kkk=jcny[m]; kkk*=jc[n]; kkk%=p; kkk*=jcny[n-m]; kkk%=p; return kkk; } void cn(int zl) { if(zl==1) { ans*=2; ans-=c(nn+1,nm+1); ans+=c(nn,nm+1); ans+=p; ans%=p; } if(zl==-1) { ans+=c(nn,nm+1); ans-=c(nn-1,nm+1); ans+=p; ans%=p; ans*=ny[2]; ans%=p; } } void cm(int zl) { if(zl==1) { ans+=c(nn,nm+1); } else { ans-=c(nn,nm); ans+=p; } ans%=p; } signed main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); ycl(); scanf("%lld",&q); scanf("%lld",&q); int len=316; for(rii=1;i<=100000;i++) { sy[i]=i/len+1; } for(rii=1;i<=q;i++) { scanf("%lld%lld",&x[i].n,&x[i].m); x[i].bh=i; } sort(x+1,x+q+1,cmp1); nn=1,nm=0,ans=1; for(rii=1;i<=q;i++) { if(x[i].m<nn) { while(nm>x[i].m) { cm(-1); nm--; } while(nm<x[i].m) { cm(1); nm++; } while(nn<x[i].n) { cn(1); nn++; } while(nn>x[i].n) { cn(-1); nn--; } } while(nn<x[i].n) { cn(1); nn++; } while(nn>x[i].n) { cn(-1); nn--; } while(nm>x[i].m) { cm(-1); nm--; } while(nm<x[i].m) { cm(1); nm++; } x[i].ans=ans; } sort(x+1,x+q+1,cmp2); for(rii=1;i<=q;i++) { printf("%lld\n",x[i].ans); } }
原文地址:https://www.cnblogs.com/ztz11/p/9763251.html
时间: 2024-10-06 07:20:47