老是忍不住要吐槽一句,這題面也太長了吧。。。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; }