题意:[1,n]的区间,给m个区间 [ l i , r i ] [l_i,r_i] [li,ri],每次随机选一个区间覆盖,求[1,n]被覆盖的期望次数。(n,m<=400)
Solution1:最值反演
\quad 由最值反演 E [ m a x ( S ) ] = ∑ T 包含于 S ( − 1 ) ∣ T ∣ + 1 E [ m i n ( T ) ] E[max(S)]=\sum_{T包含于S}(-1)^{|T|+1}E[min(T)] E[max(S)]=∑T包含于S(−1)∣T∣+1E[min(T)]
\quad 这里max(S)等价于[1,n]中最晚被覆盖的点的覆盖时刻。
\quad 主要思路是枚举某个区间作为最早覆盖时刻的容斥系数贡献。
\quad 设 f i , j f_{i,j} fi,j表示前i个数中第i个数选(后面n-i个数不选),且与j个已知区间有交的容斥系数贡献。
\quad 设 c n t l , r cnt_{l,r} cntl,r表示[l,r]这个区间被已知区间覆盖到的次数,
b i b_i bi表示i点被已知区间覆盖到的次数。
\quad 有转移方程 f i , k + b i − c n t i , j = ∑ j = 0 i − 1 − f j , k f_{i,k+b_i-cnt_{i,j}} = \sum_{j=0}^{i-1}-f_{j,k} fi,k+bi−cnti,j=∑j=0i−1−fj,k。
\quad 解释一下,对于含i(不含i+1n)的集合的系数贡献,可以从前面含j(不含j+1n)的集合的系数贡献转移过来。首先由于选i,集合大小会+1,那么符号要反一下。从j转移过来,也就是说1j-1不关心,j选,j+1i-1不选,i选,i+1~n不选。
\quad 所以对于第二维要减去覆盖到[j+1,i-1]的已知区间数,这个等价于覆盖i的区间数+覆盖j的区间数 - 覆盖[i,j]的区间数。
算出 f i , j f_{i,j} fi,j后怎么算答案呢?
\quad f i , j f_{i,j} fi,j——含i不含i+1~n的集合的容斥系数贡献,前面说要枚举E[min(T)],即选到有交的某个区间的期望次数,m个选到其中j个中的一个的期望次数,即 m j \frac{m}{j} jm
a n s = ∑ f i , j ∗ m j \quad ans =\sum f_{i,j}*\frac{m}{j} ans=∑fi,j∗jm
Solution2: nb但不容易想到的期望推导
首先直接上结论: a n s = ∑ s t a t e p s t a t e ∗ m c n t , 其中 s t a t e 表示拿到 c n t 个区间,且这些区间的并不是 [ 1 , n ] ans = \sum_{state}p_{state}*\frac{m}{cnt},其中state表示拿到cnt个区间,且这些区间的并不是[1,n] ans=∑statepstate∗cntm,其中state表示拿到cnt个区间,且这些区间的并不是[1,n]
前面是拿到cnt个区间,且它们的并不是[1,n],即必定还要拿其他的区间,后面就是第一次拿到其他区间的期望次数。所有状态的往下走一步的期望次数和就是答案,很nb的计算方法。
PS:第一次见期望这样算,不过式子确实没毛病😊
f i f_i fi表示取i个区间,它们并不为[1,n]的方案数
p s t a t e = C ( m , c n t ) − f c n t C ( m , c n t ) p_{state}=\frac{C(m,cnt)-f_{cnt}}{C(m,cnt)} pstate=C(m,cnt)C(m,cnt)−fcnt
现在只要求 f i f_i fi即可,可以用dp求出。
将已知区间排序后,dp[i] [j] [k]表示前i个已知区间,选了k条,它们的并为[1,j]的方案数。
要求的就是 f i = d p [ n ] [ m ] [ i ] f_i=dp[n][m][i] fi=dp[n][m][i]
转移方程,枚举加入的区间 [ l i , r i ] [l_i,r_i] [li,ri]
1,当 j < l i − 1 j<l_i-1 j<li−1时, d p i , j , k ← d p i − 1 , j , k dp_{i,j,k}\leftarrow dp_{i-1,j,k} dpi,j,k←dpi−1,j,k
2,当 l i − 1 < = j < = r i l_i-1<=j<=r_i li−1<=j<=ri时, d p i , j , k ← d p i − 1 , j , k , d p i − 1 , j , k − 1 → d p i , r i , k dp_{i,j,k}\leftarrow dp_{i-1,j,k},dp_{i-1,j,k-1} \rightarrow dp_{i,r_i,k} dpi,j,k←dpi−1,j,k,dpi−1,j,k−1→dpi,ri,k
3,当 j > r i j>r_i j>ri时, d p i , j , k ← d p i − 1 , j , k + [ k > 0 ] d p i − 1 , j , k − 1 dp_{i,j,k} \leftarrow dp_{i-1,j,k} + [k>0]dp{i-1,j,k-1} dpi,j,k←dpi−1,j,k+[k>0]dpi−1,j,k−1
最值反演
const int mod=998244353;
const double eps=1e-8;
ll qsm(int a,int b){
ll ans = 1,tmp=a;
while( b ){
if( b&1 ) ans = ans * tmp%mod;
tmp = tmp * tmp%mod;
b>>=1;
}
return ans;
}
int n,m;
int cnt[N][N];//区间[l,r]被给定区间覆盖的次数
pii line[N];
int f[N][N];//1~i-1任意,i必选,i+1~n不选的集合的∑容斥系数
int b[N];//点i被已知区间覆盖的次数
bool in(int i,int j){return line[j].fi<=i&&i<=line[j].se;}
signed main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
IOS;
cin>>n>>m;
_for(i,1,m) cin>>line[i].fi>>line[i].se;
_for(i,1,n)
_for(j,1,n)
_for(k,1,m)
if( in(i,k)&&in(j,k) ) cnt[i][j]++;
_for(i,1,n)
_for(j,1,m) b[i] += in(i,j);
f[0][0] = mod-1;//空集容斥,不过最后对答案没有贡献
_for(i,1,n)
_for(j,0,i-1)
_for(k,0,m){
f[i][k+b[i]-cnt[i][j]] = (f[i][k+b[i]-cnt[i][j]] - f[j][k]+mod)%mod;
}
int ans = 0;
_for(i,1,n){
_for(j,0,m) ans = (ans + f[i][j]*m%mod*qsm(j,mod-2)%mod)%mod;
}
cout<<ans<<endl;
AC;
}
nb期望
const int N=400+10;
const int mod=998244353;
const double eps=1e-8;
pii line[N];
int n,m;
int f[N][N][N];
int fac[N],ni_f[N];
ll qsm(int a,int b){
ll ans=1,tmp=a;
while( b ) {
if( b&1 ) ans = ans * tmp%mod;
tmp = tmp * tmp%mod;
b>>=1;
}
return ans;
}
void ini(){
int maxn = 400;
fac[0]=1;
_for(i,1,maxn) fac[i] = (fac[i-1] * i)%mod;
ni_f[maxn] = qsm(fac[maxn],mod-2);
_rep(i,maxn-1,0) ni_f[i] = ni_f[i+1] * (i+1)%mod;
}
ll C(int n,int m){
if( m==n || m==0 ) return 1;
if( n < m ) return 0;
return fac[n] * ni_f[n-m]%mod * ni_f[m]%mod;
}
//fijk,排序后,前i条线段,选k条,它们的并为[1,j],方案数
signed main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
IOS;
ini();
cin>>n>>m;
_for(i,1,m) cin>>line[i].fi>>line[i].se;
sort(line+1,line+1+m);
f[0][0][0]=1;
_for(i,1,m){
_rep(j,n,0){
_for(k,0,m){
auto [L,R] = line[i];
if( j < L - 1 ) f[i][j][k] += f[i-1][j][k],f[i][j][k]%=mod;
else if( j<=R ){
f[i][j][k] += f[i-1][j][k],f[i][j][k]%=mod;
if( k ) f[i][R][k] += f[i-1][j][k-1],f[i][R][k]%=mod;
}
else {
f[i][j][k] += f[i-1][j][k],f[i][j][k]%=mod;
if( k ) f[i][j][k] += f[i-1][j][k-1],f[i][j][k]%=mod;
}
}
}
}
int ans = 0;
_for(i,0,m){
ans = (ans + (C(m,i) - f[m][n][i] +mod)%mod * qsm(C(m,i),mod-2)%mod * m %mod
* qsm(m-i,mod-2)%mod)%mod;
}
cout<<ans<<endl;
AC;
}