「LG3600-随机数生成器」题解

P3600 随机数生成器

sol

期望不太方便,转计数。那么就是要求对每个值,最后结果恰为这个值的方案数。

恰好不太好求,考虑差分,转化为至多,那么就是要对每个值求答案不超过这个值的方案数。

要求所有区间区间内最小值的最大值不超过标准值,也就是要求每个区间都得有一个不超过标准值的数。容易将原序列转化为 0-1 序列,再转化为线段覆盖问题:要求放一些点点,使得每个给出的区间内都包含有一个点。求放点方案数。

首先不难发现不存在包含关系的区间,因为小区间满足大区间必然满足。那么现在区间右端点关于左端点不降。

考虑 DP 求这个,设计 \(f(i,j)\) 表示前 \(i\) 个点共选了 \(j\) 个点且钦定选第 \(i\) 个点使得所有左端点不超过 \(i\) 的区间均满足性质的方案数。转移考虑枚举上一个合法点的位置,那么简单预处理出覆盖各个点的最左的区间与最右的区间,则上一个合法点必须位于当前点前最后一个不被当前点覆盖的区间内。这个显然可以简单前缀和优化。

求出 \(f\) 之后找方案数是简单的,枚举标准值 \(v\) 与总放点数 \(i\),有系数 \(i^v(n-i)^{x-v}\),意义显然。最后枚举答案差分得到方案并除总方案数得到期望即可。

code

const int N=2005;

int n,x,q,m;
struct node{int l,r;}ns[N],ls[N];
int lb[N],rb[N];

int dtl[N<<2],dtr[N<<2],lzl[N<<2],lzr[N<<2];
void build(int x=1,int l=1,int r=n){
    dtl[x]=lzl[x]=inf;
    dtr[x]=lzr[x]=-inf;
    if(l==r)return;
    int m=l+r>>1;
    build(x<<1,l,m);
    build(x<<1|1,m+1,r);
}
void pushdown(int x){
    chmin(dtl[x<<1],lzl[x]);
    chmin(dtl[x<<1|1],lzl[x]);
    chmin(lzl[x<<1],lzl[x]);
    chmin(lzl[x<<1|1],lzl[x]);
    chmax(dtr[x<<1],lzr[x]);
    chmax(dtr[x<<1|1],lzr[x]);
    chmax(lzr[x<<1],lzr[x]);
    chmax(lzr[x<<1|1],lzr[x]);
    lzl[x]=inf,lzr[x]=-inf;
}
void modify(int lq,int rq,int v,int x=1,int l=1,int r=n){
    if(lq<=l&&r<=rq)return chmin(dtl[x],v),chmin(lzl[x],v),chmax(dtr[x],v),chmax(lzr[x],v),void();
    int m=l+r>>1;
    pushdown(x);
    if(lq<=m)modify(lq,rq,v,x<<1,l,m);
    if(m<rq)modify(lq,rq,v,x<<1|1,m+1,r);
}
pii query(int k,int x=1,int l=1,int r=n){
    if(l==r)return {dtl[x],dtr[x]};
    int m=l+r>>1;
    pushdown(x);
    if(k<=m)return query(k,x<<1,l,m);
    else return query(k,x<<1|1,m+1,r);
}

mint f[N][N],s[N][N];
mint g[N],ans;

inline void Main(){
    cin>>n>>x>>q;
    rep(i,1,q)cin>>ns[i].l>>ns[i].r;
    sort(ns+1,ns+1+q,[&](node a,node b){if(a.l!=b.l)return a.l<b.l;return a.r<b.r;});
    int mx=inf;
    per(i,q,1)if(ns[i].r<mx)mx=ns[i].r,ls[++m]=ns[i];
    reverse(ls+1,ls+1+m);
    build();
    rep(i,1,m)modify(ls[i].l,ls[i].r,i);
    rep(i,1,n){
        pii res=query(i);
        if(res.fir!=inf)lb[i]=res.fir,rb[i]=res.sec;
        else rb[i]=rb[i-1],lb[i]=rb[i]+1;
    }
    f[0][0]=s[0][0]=1;
    rep(i,1,n)s[i][0]+=s[i-1][0];
    rep(j,1,n){
        rep(i,j,n){
            f[i][j]=s[i-1][j-1]-(ls[lb[i]-1].l-1<0?0:s[ls[lb[i]-1].l-1][j-1]);
            s[i][j]+=f[i][j];
        }
        rep(i,1,n)s[i][j]+=s[i-1][j];
    }
    rep(v,1,x)rep(i,1,n)g[v]+=(s[n][i]-s[ls[m].l-1][i])*qpow(v,i)*qpow(x-v,n-i);
    rep(v,1,x)ans+=v*(g[v]-g[v-1]);
    put(ans/qpow(x,n));
}
posted @ 2025-10-27 17:40  LastKismet  阅读(4)  评论(0)    收藏  举报