老是忍不住要吐槽一句,这题面也太长了吧。。。php
首先,确定要把咱们要求的东西推成一个式子,否则怎么可能作题。。。html
设
表示当前以
为最大值的方案数。
那么
以后的数显然是单调递减且连续,方案数为
。
考虑前
个位置,放法数就是
因此咱们如今获得递推式
,
。c++
转换一下 git
因此获得通项公式 web
那么询问的答案就是
数据范围
,果断莫队。
令
咱们只须要找到根据
更新答案的较小复杂度方法就好了
幸运的是,这个式子在
和
的时候都有
的转移方式。app
首先
的转移:
这个转移十分显然,就是直接根据表达式转移。svg
而
的转移须要一点技巧:
怎么求
spa
因为帕斯卡三角形上的组合数递推公式 。咱们把上面这个式子拆开获得 .net
因此其实就是
把刚才退出来的
的式子代进来获得
利用这个式子能够推出
的状况:
code
那么就能够上莫队了。
注意能将 变大的时候尽可能先移动 ,不然先移动 ,避免转移通过非法组合数就 了。
代码:
#include<bits/stdc++.h> using namespace std; #define re register #define gc getchar #define pc putchar #define cs const inline int getint(){ re int num; re char c; while(!isdigit(c=gc()));num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } inline void outint(long long a){ static char ch[23]; if(a==0)pc('0'); while(a)ch[++ch[0]]=a-a/10*10,a/=10; while(ch[0])pc(ch[ch[0]--]^48); } cs int N=100005; cs int mod=19260817; int fac[N],inv[N],ifac[N]; int pow2[N]; inline int C(int n,int m){ return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod; } int l=1,r=1,now=1; inline void ll(){now=(1ll*now-1ll*C(r,l)*pow2[l-1]%mod+mod)%mod;--l;} inline void lr(){now=(1ll*now+1ll*C(r,l+1)*pow2[l]%mod)%mod;++l;} inline void rl(){now=(1ll*now+1ll*C(r-1,l)*pow2[l]%mod-1ll*C(r,0)*pow2[0]%mod+mod)%mod*inv[3]%mod;--r;} inline void rr(){now=(3ll*now-1ll*C(r,l)*pow2[l]%mod+1ll*C(r,0)*pow2[0]%mod+mod)%mod;++r;} struct Query{int l,r,id;}Q[N]; int ans[N],block[N],B,bcnt; inline bool cmp(cs Query &a,cs Query &b){ if(block[a.l]^block[b.l])return block[a.l]<block[b.l]; return (block[a.l]&1)^(a.r>b.r); } int n,m,q; int maxn; signed main(){ fac[0]=fac[1]=inv[0]=inv[1]=ifac[0]=ifac[1]=pow2[0]=1; pow2[1]=2; for(int re i=2;i<N;++i){ fac[i]=1ll*fac[i-1]*i%mod; inv[i]=1ll*(mod-mod/i)*inv[mod-mod/i*i]%mod; ifac[i]=1ll*ifac[i-1]*inv[i]%mod; pow2[i]=(pow2[i-1]<<1)%mod; } q=getint(); for(int re i=1;i<=q;++i){ Q[i].id=i; Q[i].r=getint(); Q[i].l=getint(); maxn=max(Q[i].r,maxn); } B=sqrt(maxn);bcnt=1; for(int re i=1;i<=maxn;++i){ block[i]=bcnt; if(i%B==0)++bcnt; } sort(Q+1,Q+q+1,cmp); for(int re i=1;i<=q;++i){ if(Q[i].r>=r){ while(r<Q[i].r)rr(); while(r>Q[i].r)rl(); while(l<Q[i].l)lr(); while(l>Q[i].l)ll(); } else{ while(l<Q[i].l)lr(); while(l>Q[i].l)ll(); while(r>Q[i].r)rl(); while(r<Q[i].r)rr(); } ans[Q[i].id]=now; } for(int re i=1;i<=q;++i)outint(ans[i]),pc('\n'); return 0; }