U430605 组合数前缀和 题解
U430605 组合数前缀和 题解
题意分析
略。
思路分析
设 \(f_{n,m}=\sum_{i=0}^{m}\operatorname{C}_{i}^{n}\)。
那么我们发现,从 \(f_{n,m}\) 其实可以方便地转移到 \(f_{n,m+1},f_{n,m-1}\),因此我们可以考虑尝试莫队,不过还要推出剩下的两个转移式:
\[\begin{aligned}
f_{n,m} & = \sum_{i=0}^{m} \operatorname{C}_{i}^{n} \\
f_{n,m} & = \sum_{i=0}^{m} \operatorname{C}_{i-1}^{n-1} + \operatorname{C}_{i}^{n-1} \\
f_{n,m} & = \sum_{i=0}^{m} \operatorname{C}_{i}^{n-1} + \sum_{i=0}^{m-1} \operatorname{C}_{i}^{n-1} \\
f_{n,m} & = 2 f_{n-1,m} - \operatorname{C}_{m}^{n-1} \\
\end{aligned}
\]
由此,我们推得四个转移式:
\[\begin{aligned}
f_{n-1,m} & = \frac{f_{n,m}+\operatorname{C}_{m}^{n-1}}{2} \\
f_{n+1,m} & = 2f_{n,m} - \operatorname{C}_{m}^{n} \\
f_{n,m-1} & = f_{n,m} - \operatorname{C}_{m}^{n} \\
f_{n,m+1} & = f_{n,m} + \operatorname{C}_{m+1}^{n} \\
\end{aligned}
\]
我们将莫队延展到数学式的参数上,就可以求得答案。
现在分析时间复杂度:假设莫队分块长度 \(S\),则块数为 \(O(\frac{n}{S})\) 级别,左指针在单块内时,右指针移动次数级别最大为 \(O(n)\),左指针单次移动次数最大为 \(O(S)\),所有单次移动都可以优化到 \(O(1)\),所以总时间复杂度为 \(O(QS+\frac{n^2}{S})\),求导后,可知块长为 \(\frac{n}{\sqrt{Q}}\) 时,最小平衡到 \(O(n\sqrt{Q})\)。
CODE
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define max(a,b) ((a)<(b)?(b):(a))
#define min(a,b) ((a)>(b)?(b):(a))
#define tomax(a,b) ((a)=max((a),(b)))
#define tomin(a,b) ((a)=min((a),(b)))
#define RCL(a,b,c,d) memset((a),(b),sizeof(c)*(d))
#define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
#define DOR(i,a,b) for(register int i=(a);i>=(b);--i)
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0);return Main();}signed Main
using namespace std;
constexpr int N=1e5+10;
namespace Modular_Arithmetic{
#define MOD 73939133
#define toadd(a,b) ((a)=add((a),(b)))
#define tomul(a,b) ((a)=mul((a),(b)))
int fac[N],inv[N];
template<typename T1,typename T2>constexpr auto add(T1 a,T2 b){
return a+b>=MOD?a+b-MOD:a+b<0?a+b+MOD:a+b;
}
template<typename T1,typename T2>constexpr auto mul(T1 a,T2 b){
return (long long)a*b%MOD;
}
template<typename T,typename...Types>constexpr auto add(T a,Types... b){
return add(a,add(b...));
}
template<typename T,typename...Types>constexpr auto mul(T a,Types... b){
return mul(a,mul(b...));
}
int Pow(int a,int b){
int res=1;
for(a%=MOD;b;b>>=1,tomul(a,a))if(b&1)tomul(res,a);
return res;
}
void Init(int n){
fac[0]=1;
FOR(i,1,n)fac[i]=mul(fac[i-1],i);
inv[n]=Pow(fac[n],MOD-2);
DOR(i,n,1)inv[i-1]=mul(inv[i],i);
}
int C(int n,int m){
return (n<0||m<0||n<m)?0:mul(fac[n],inv[n-m],inv[m]);
}
}using namespace Modular_Arithmetic;
int n,m,l,r,Q,Bl,Mx,sum;
int ans[N];
struct Query{
int l,r,id,idx;
friend bool operator <(Query a,Query b){
return a.id^b.id?a.l<b.l:(a.r>=b.r)^(a.id&1);
}
}qr[N];
signed main(){
rd(Q);
FOR(i,1,Q)rd(qr[i].r),rd(qr[i].l),tomin(qr[i].l,qr[i].r),qr[i].idx=i,tomax(Mx,qr[i].r);
Bl=ceil(1.0*Mx/sqrt(Q)),Init(Mx);
FOR(i,1,Q)qr[i].id=(qr[i].l-1)/Bl+1;
sort(qr+1,qr+Q+1);
l=0,r=1,sum=1;
FOR(i,1,Q){
for(;r<qr[i].r;++r)sum=add(mul(2,sum),-C(r,l));
for(;l>qr[i].l;--l)toadd(sum,-C(r,l));
for(;r>qr[i].r;--r)sum=mul(add(sum,C(r-1,l)),inv[2]);
for(;l<qr[i].l;++l)toadd(sum,C(r,l+1));
ans[qr[i].idx]=sum;
}
FOR(i,1,Q)wr(ans[i]);
return 0;
}

浙公网安备 33010602011771号