孤立集

Description

对于一个正整数集合\(S\),如果存在\(k\in S\)且满足\(k-1\notin S\)\(k+1\notin S\),则称\(k\)\(S\)中的一个「孤立元」。

给定一个集合\(A=\{1,2,\cdots,n\}\),并等概率的选出它的一个恰好含有\(m\)个元素的子集\(B\),你的任务是,计算\(B\)中所有孤立元的和的数学期望值。


很容易想到对于\(1,n\)被选为孤立集的概率是一样的,\([2,n-1]\)被选为孤立集的概率是一样的

先考虑1和n:被选的概率是\(\frac{n}{m}\) 要使n不是孤立集需要满足\(n-1\)同时被选,不是孤立集概率\(\frac{m}{n}\frac{m-1}{n-1}\),那么这一部分的期望就是\((1+n)(\frac m n-\frac{m}{n}\frac{m-1}{n-1})\)画一下柿子\((1+n)\frac m n\frac{n-m}{n-1}\)

然后是\([2,n-1]\):\(\forall \ k \in [2,n-1]\)被选的概率同样是\(\frac{m}{n}\)而由于左右两边被选都不合法,所以是孤立集的概率就是

\[\frac m n -2\times \frac{m}{n}\frac{m-1}{n-1}+\frac{m}{n}\frac{m-1}{n-1}\frac{m-2}{n-2}\]

画柿子后 \[\frac m n \frac{n-2\times m+1}{n-1}\]


#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define M 998244353
using namespace std;

LL i,m,n,j,k,t,c[2000001],inv[2000001];

int main()
{
    scanf("%lld",&t); inv[1]=1;
    for(int i=1;i<=1500000;i++) c[i]=(c[i-1]+i)%M;
    for(int i=2;i<=1500000;i++) inv[i]=(M-M/i)%M*inv[M%i]%M;
    for(;t;t--)
    {
        scanf("%lld%lld",&n,&m);
        if(m==1)
        {
            printf("%lld\n",c[n]*inv[n]%M);
            continue;
        }
        if(n==m || m==0)
        {
            printf("0\n");
            continue;
        }
        LL ans=(  (m*inv[n] %M*(n-m) %M*inv[n-1] %M*(n+1) %M)%M  +((m*inv[n] %M*(n-2*m+1) %M*inv[n-1] %M +m*inv[n] %M*(m-1) %M*inv[n-1] %M*(m-2) %M*inv[n-2] %M)%M*(c[n-1]-1)%M)%M)%M;
        ans%=M;
        if(ans<0) ans+=M;
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/ZUTTER/p/10197559.html