莫名就跑到了
l
o
j
r
k
1
?
loj\ rk1?
loj rk1?
理解不能
首先可以列出一个显然的
D
P
DP
DP
设
f
l
,
r
,
x
f_{l,r,x}
fl,r,x表示
[
l
,
r
]
[l,r]
[l,r]最大值为
x
x
x的方案数
那么显然有
f
l
,
r
,
x
=
∑
k
,
∣
r
−
k
+
l
−
k
∣
≤
2
(
∑
y
≤
x
f
l
,
k
−
1
,
x
)
(
∑
y
<
x
f
k
+
1
,
r
,
x
)
f_{l,r,x}=\sum_{k,|r-k+l-k|\le2}(\sum_{y\le x}f_{l,k-1,x})(\sum_{y<x}f_{k+1,r,x})
fl,r,x=k,∣r−k+l−k∣≤2∑(y≤x∑fl,k−1,x)(y<x∑fk+1,r,x)
考虑如果对于
A
,
B
A,B
A,B无限制时
可以归纳的得到
f
l
,
r
f_{l,r}
fl,r是关于
x
x
x的
r
−
l
+
1
r-l+1
r−l+1次多项式
由于
x
x
x太大考虑用系数表示
则转移时前缀和实际上是一个离散积分
就是求
y
≤
x
y\le x
y≤x时
f
l
,
r
(
y
)
f_{l,r}(y)
fl,r(y)用
x
x
x表示的和
如果直接用普通多项式求并不优秀
考虑用下降幂多项式
由于有
x
j
‾
−
(
x
−
1
)
j
‾
=
j
(
x
−
1
)
j
−
1
‾
x^{\underline j}-(x-1)^{\underline j}=j(x-1)^{\underline {j-1}}
xj−(x−1)j=j(x−1)j−1
则
x
i
‾
=
(
x
+
1
)
i
+
1
‾
−
x
i
+
1
‾
i
+
1
x^{\underline i}=\frac{(x+1)^{\underline{i+1}}-x^{\underline {i+1}}}{i+1}
xi=i+1(x+1)i+1−xi+1
那么
∑
x
=
1
n
x
i
‾
=
∑
i
=
1
n
(
x
+
1
)
i
+
1
‾
−
x
i
+
1
‾
i
+
1
\sum_{x=1}^nx^{\underline i}=\frac{\sum_{i=1}^n{(x+1)}^{\underline{i+1}}-x^{\underline {i+1}}}{i+1}
x=1∑nxi=i+1∑i=1n(x+1)i+1−xi+1
=
(
n
+
1
)
i
+
1
‾
−
[
i
=
1
]
i
+
1
=\frac{(n+1)^{\underline{i+1}}-[i=1]}{i+1}
=i+1(n+1)i+1−[i=1]
则例如
∑
i
=
1
x
−
1
∑
j
a
j
i
j
‾
=
∑
j
a
j
∑
i
=
1
x
−
1
i
j
‾
=
∑
j
a
j
x
j
+
1
‾
j
+
1
\sum_{i=1}^{x-1}\sum_{j}a_ji^{\underline j}=\sum_ja_j\sum_{i=1}^{x-1}i^{\underline j}=\sum_ja_j\frac{x^{\underline {j+1}}}{j+1}
i=1∑x−1j∑ajij=j∑aji=1∑x−1ij=j∑ajj+1xj+1
于是对于下降幂多项式可以做到
O
(
n
)
O(n)
O(n)求前缀和
那么还需要做的就是对于下降幂多项式相加相乘
至于相乘
可以
m
t
t
mtt
mtt做到
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
但是没有必要
考虑怎么做
O
(
n
2
)
O(n^2)
O(n2)的乘法
对于
∑
i
a
i
x
i
‾
∗
∑
i
b
i
x
i
‾
\sum_i a_ix^{\underline i}*\sum_ib_ix^{\underline i}
∑iaixi∗∑ibixi
那么对于左边的
x
i
‾
x^{\underline i}
xi,右边应该拿
(
x
−
i
)
j
‾
(x-i)^{\underline j}
(x−i)j来乘
又有
x
j
‾
−
(
x
−
1
)
j
‾
=
j
(
x
−
1
)
j
−
1
‾
x^{\underline j}-(x-1)^{\underline j}=j(x-1)^{\underline {j-1}}
xj−(x−1)j=j(x−1)j−1
于是可以每次
O
(
n
)
O(n)
O(n)的将
∑
i
b
i
x
i
‾
\sum_ib_ix^{\underline i}
∑ibixi变成
∑
i
b
i
(
x
−
1
)
i
‾
\sum_ib_i(x-1)^{\underline i}
∑ibi(x−1)i
现在考虑有
A
,
B
A,B
A,B的限制
那么可以离散化成
O
(
n
)
O(n)
O(n)个区间
每个区间内部的多项式是一样的
于是变成维护分段下降幂多项式
其他处理是一样的
记忆化搜索实现这个
D
P
DP
DP
复杂度为
O
(
n
∑
l
,
r
[
区
间
l
,
r
合
法
]
(
r
−
l
+
1
)
2
)
O(n\sum_{l,r}[区间l,r合法](r-l+1)^2)
O(n∑l,r[区间l,r合法](r−l+1)2)
据说分析出来就是
O
(
n
3
)
O(n^3)
O(n3)的
确实跑的飞快
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline ll readll(){
char ch=gc();
ll res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
return top;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
cs int N=305;
int iv[N];
inline void init_inv(){
iv[0]=iv[1]=1;
for(int i=2;i<N;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
}
typedef vector<int> poly;
inline int F(cs poly &f,int x){
int res=0;
for(int i=0,mt=1;i<f.size();Mul(mt,x-i),i++)Add(res,mul(f[i],mt));
return res;
}
inline poly operator +(poly a,poly b){
a.resize(max(a.size(),b.size()));
for(int i=0;i<b.size();i++)Add(a[i],b[i]);
return a;
}
inline poly operator *(poly a,poly b){
int deg=a.size()+b.size()-1;
poly c(deg,0);
for(int i=0;i<a.size();i++){
for(int j=0;j<b.size();j++)Add(c[i+j],mul(a[i],b[j]));
for(int j=1;j<b.size();j++)Add(b[j-1],mul(b[j],j));
}
return c;
}
inline poly integ(poly a){
a.pb(0);
for(int i=a.size()-1;i;i--)a[i]=mul(a[i-1],iv[i]);
a[0]=0;return a;
}
typedef pair<poly,int> pi;
typedef vector<pi> Poly;
inline Poly operator +(cs Poly &a,cs Poly &b){
Poly c;int i=0,j=0,lim=0;
while(0721){
c.pb(pi(a[i].fi+b[j].fi,lim));
if(i+1==a.size()&&j+1==b.size())break;
if(i+1<a.size()&&(j+1==b.size()||a[i+1].se<b[j+1].se))
lim=a[++i].se;else lim=b[++j].se;
if(i+1<a.size()&&a[i+1].se<=lim)i++;
if(j+1<b.size()&&b[j+1].se<=lim)j++;
}
return c;
}
inline Poly operator *(cs Poly &a,cs Poly &b){
Poly c;int i=0,j=0,lim=0;
while(0721){
c.pb(pi(a[i].fi*b[j].fi,lim));
if(i+1==a.size()&&j+1==b.size())break;
if(i+1<a.size()&&(j+1==b.size()||a[i+1].se<b[j+1].se))
lim=a[++i].se;else lim=b[++j].se;
if(i+1<a.size()&&a[i+1].se<=lim)i++;
if(j+1<b.size()&&b[j+1].se<=lim)j++;
}
return c;
}
inline Poly cut(cs Poly &a,int l,int r){
Poly b;b.pb(pi(poly(1),0));
for(int i=0;i<a.size();i++){
if(a[i].se<=r&&(i+1==a.size()||a[i+1].se>l))
b.pb(pi(a[i].fi,max(l,a[i].se)));
}
b.pb(pi(poly(1),r+1));
return b;
}
inline Poly integ(cs Poly &a){
Poly b;
for(int i=0;i<a.size();i++){
b.pb(pi(integ(a[i].fi),a[i].se));
if(i)b[i].fi[0]=dec(F(b[i-1].fi,a[i].se),F(b[i].fi,a[i].se));
}return b;
}
Poly f[2505];
int n,id[N][N],tot,L[N],R[N];
void dfs(int l,int r){
if(id[l][r])return;
id[l][r]=++tot;
int u=id[l][r];
f[u].pb(pi(poly(1,0),0));
if(l>r){f[u][0].fi[0]=1;return;}
for(int i=l;i<=r;i++)if(abs(r-i-(i-l))<=2){
dfs(l,i-1),dfs(i+1,r);
Poly vl=f[id[l][i-1]],vr=f[id[i+1][r]];
if(l<i)vl=vl+integ(vl);
if(i<r)vr=integ(vr);
f[u]=f[u]+cut(vl*vr,L[i],R[i]);
}
}
int main(){
freopen("robot.in","r",stdin);
freopen("robot.out","w",stdout);
n=read();
init_inv();
for(int i=1;i<=n;i++)L[i]=read(),R[i]=read();
dfs(1,n);
cout<<integ(f[id[1][n]]).back().fi[0]<<'\n';
return 0;
}