传送门
神题 O r z Orz Orz
首先 50 p t s 50pts 50pts大家应该都会。。。
直接设 f l , r , x f_{l,r,x} fl,r,x表示区间 [ l , r ] [l,r] [l,r]中最大值为 x x x的方案数,然后枚举最大值出现位置转移即可。
复杂度?
由于对于每个区间 [ l , r ] [l,r] [l,r]只有 2 / 3 2/3 2/3个点可以用于转移,所以前两维总状态数大概是 O ( n ) O(n) O(n)级别的。
而对于最后一维,貌似不好优化。
考虑到最后取值的区间只有 O ( n ) O(n) O(n)段,我们不妨重新设一个状态:
f l , r , t , x ′ f'_{l,r,t,x} fl,r,t,x′表示对于区间 [ l , r ] [l,r] [l,r]最大值在第 t t t段内且等于 x x x。
然后经过数学归纳会发现在同一区间同一段取值区间内的数对应一个相同的函数。
即 f l , r , t , x ′ f'_{l,r,t,x} fl,r,t,x′是关于 x x x的多项式 f l , r , t ′ ( x ) f'_{l,r,t}(x) fl,r,t′(x)。
那么 f l , r , x f_{l,r,x} fl,r,x就是关于 x x x的分段多项式 f l , r ( x ) f_{l,r}(x) fl,r(x)
考虑如何从 f l , m i d f_{l,mid} fl,mid和 f m i d + 1 , r f_{mid+1,r} fmid+1,r转移过来。
发现只需求出 f l , m i d f_{l,mid} fl,mid和 f m i d + 1 , r f_{mid+1,r} fmid+1,r的前缀和然后乘起来即可。
于是就用下降幂多项式快速幂搞一搞QwQ。
注意这题模数是 1 e 9 + 7 1e9+7 1e9+7,所以下降幂多项式的乘法要么写 O ( n 2 ) O(n^2) O(n2)的要么就只能 m t t mtt mtt,由于博主太懒选择了前者QwQ。
现在考虑如何 O ( n 2 ) O(n^2) O(n2)做下降幂多项式乘法。
我们考虑有两个下降幂多项式,按次数从小到大枚举第一个多项式的项。
然后对于第一个多项式的 x i ‾ x^{\underline i} xi,第二个多项式应该用 ( x − i ) j ‾ (x-i)^{\underline j} (x−i)j的系数去转移,不幸的是我们存的是 x j ‾ x^{\underline j} xj的系数。
于是我们每次处理完第一个多项式当前第 i i i项的贡献之后需要将第二个多项式所有的 ( x − i ) j ‾ (x-i)^{\underline j} (x−i)j变成 ( x − i − 1 ) j ‾ (x-i-1)^{\underline j} (x−i−1)j。
于是又用到了这个等式 x k ‾ = ( x − 1 ) k ‾ + k ( x − 1 ) k − 1 ‾ x^{\underline k}=(x-1)^{\underline k}+k(x-1)^{\underline{k-1}} xk=(x−1)k+k(x−1)k−1
然后就能 O ( n 2 ) O(n^2) O(n2)做下降幂多项式乘法啦。
剩下的都不太难。
代码:
#include
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef long long ll;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=305;
struct poly{
vector<int>a;
int deg;
poly(int k=0){a.resize((deg=k)+1);}
inline int&operator[](const int&k){return a[k];}
inline const int&operator[](const int&k)const{return a[k];}
inline int f(int x){
int ret=0;
for(ri mt=1,i=0;i<=deg&&mt;Mul(mt,x-i),++i)Add(ret,mul(mt,a[i]));
return ret;
}
friend inline poly operator+(const poly&a,const poly&b){
int n=a.deg,m=b.deg;
poly c(max(n,m));
for(ri i=0;i<=n;++i)Add(c[i],a[i]);
for(ri i=0;i<=m;++i)Add(c[i],b[i]);
return c;
}
friend inline poly operator*(poly a,poly b){
int n=a.deg,m=b.deg;
poly c(n+m);
for(ri i=0;i<=n;++i){
for(ri j=0;j<=m;++j)Add(c[i+j],mul(a[i],b[j]));
for(ri j=1;j<=m;++j)Add(b[j-1],mul(b[j],j));
}
return c;
}
};
int inv[N];
inline poly poly_inter(poly a){
poly ret(a.deg+1);
for(ri i=0;i<=a.deg;++i)ret[i+1]=mul(a[i],inv[i+1]);
return ret;
}
struct F{
vector<pair<poly,int> >a;
int n;
F(){a.clear(),n=-1;}
inline pair<poly,int>&operator[](const int&k){return a[k];}
inline const pair<poly,int>&operator[](const int&k)const{return a[k];}
inline void insert(pair<poly,int>v){++n,a.push_back(v);}
friend inline F operator+(const F&a,const F&b){
F ret;
int ca=0,cb=0,lim=0,n=a.n,m=b.n;
while(1){
ret.insert(make_pair(a[ca].fi+b[cb].fi,lim));
if(ca>=n&&cb>=m)break;
lim=(ca<n)&&(cb>=m||a[ca+1].se<b[cb+1].se)?a[++ca].se:b[++cb].se;
while(ca<n&&a[ca+1].se<=lim)++ca;
while(cb<m&&b[cb+1].se<=lim)++cb;
}
return ret;
}
friend inline F operator*(const F&a,const F&b){
F ret;
int ca=0,cb=0,lim=0,n=a.n,m=b.n;
while(1){
ret.insert(make_pair(a[ca].fi*b[cb].fi,lim));
if(ca>=n&&cb>=m)break;
lim=(ca<n)&&(cb>=m||a[ca+1].se<b[cb+1].se)?a[++ca].se:b[++cb].se;
while(ca<n&&a[ca+1].se<=lim)++ca;
while(cb<m&&b[cb+1].se<=lim)++cb;
}
return ret;
}
inline F getF(int ql,int qr){
F ret;
ret.insert(make_pair(poly(0),0));
for(ri i=0;i<=n;++i)if(a[i].se<=qr&&(i==n||a[i+1].se>ql))ret.insert(make_pair(a[i].fi,max(a[i].se,ql)));
ret.insert(make_pair(poly(0),qr+1));
return ret;
}
inline F inter(){
F ret;
for(ri i=0;i<=n;++i){
ret.insert(make_pair(poly_inter(a[i].fi),a[i].se));
if(i)ret[i].fi[0]=dec(ret[i-1].fi.f(ret[i].se),ret[i].fi.f(ret[i].se));
}
return ret;
}
}f[N*55];
int n,id[N][N],cnt=0,L[N],R[N];
void dfs(int l,int r){
if(id[l][r])return;
int t=id[l][r]=++cnt;
f[t].insert(make_pair(poly(0),0));
if(l>r){f[t][0].fi[0]=1;return;}
F fl,fr;
for(ri i=l;i<=r;++i){
if(abs(r+l-i*2)>2)continue;
dfs(l,i-1),dfs(i+1,r);
fl=f[id[l][i-1]],fr=f[id[i+1][r]];
if(l<i)fl=fl+fl.inter();
if(i<r)fr=fr.inter();
f[t]=f[t]+(fl*fr).getF(L[i],R[i]);
}
}
int main(){
n=read(),inv[1]=1;
for(ri i=2;i<=n;++i)inv[i]=mul(inv[mod-mod/i*i],mod-mod/i);
for(ri i=1;i<=n;++i)L[i]=read(),R[i]=read();
dfs(1,n);
cout<<f[id[1][n]].inter().a.back().fi[0];
return 0;
}