标签:tin esc cpp 子集 正整数 \n display 左右 期望值
对于一个正整数集合\(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);
}
}
标签:tin esc cpp 子集 正整数 \n display 左右 期望值
原文地址:https://www.cnblogs.com/ZUTTER/p/10197559.html