Cry_For_theMoon  

传送门

比赛的时候无伤前六题,这题来不做了于是口胡了一波 \(O(n\sqrt n\log n)\)(其实就是正解里用 set 维护了有意义的值)然后补题的时候被卡常了www

E、F、G 质量都不错。

题意:

给定长度为 \(n\) 的序列,每个元素有一个颜色 \(c_i\)。对于每个 \(k \in [1,n]\),回答从 \(n\) 个元素里任选 \(k\) 个不重复的元素,所得到的不同颜色数的期望。答案模 \(998244353\)

Data range:\(n \le 5\,\times 10^4,c_i \le 10^9\)

分析:

你发现这个 \(c \le 10^9\) 的只是出题人为了恶心你让你离散化的。

然后我们考虑设 \(f\) 为我们所求答案。对于 \(f(1)\sim f(n)\) 我们分别计算其期望。考虑期望线性性,我们分别考虑每种颜色被选中的概率(因为每种颜色对答案的贡献都为 \(1\) 所以其期望就等于概率)。设有 \(m\) 种不同颜色,第 \(i\) 种颜色的出现次数为 \(cnt_i\)。则有:

\[f(k)=\sum_{i=1}^{n}\frac{\dbinom{n}{k}-\dbinom{n-cnt_i}{k}}{\dbinom{n}{k}} \]

有一个sb第一眼没有想到分子还能容斥计算。

你发现这个式子,单次求是 \(O(nm)\) 的,那么我们来一组每个数颜色都不一样的数目就能把做法卡到平方级别。但是我们观察到式子里,对于颜色 \(i\),我们只关心它的出现次数,那么我们可以作这样的转化:设 \(g(i)\) 是出现次数为 \(i\) 的颜色个数,那么 \(f\) 可以改写为:

\[f(k)=\sum_{i=1}^{n}g(i)\frac{\dbinom{n}{k}-\dbinom{n-i}{k}}{\dbinom{n}{k}} \]

然后一个经典的结论是 \(g(i)\neq 0\)\(i\) 值是 \(O(\sqrt n)\) 级别的,这是因为 \(y=\sum_{i=1}^{x}i\)\(O(x^2)\) 的。CF远古时期就有拿这个 trick 加入多重背包的人...

所以枚举 \(g(i)\) 不为 \(0\)\(O(\sqrt n)\) 个,这些数可以预处理出来(我用个set被卡常了...)。这样单次询问就是 \(O(\sqrt n)\) 的,总时间复杂度为 \(O(n \sqrt n)\)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define op(x) ((x&1)?x+1:x-1)
#define odd(x) (x&1)
#define even(x) (!odd(x))
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define lowbit(x) (x&-x)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define next Cry_For_theMoon
#define il inline
#define pb(x) push_back(x)
#define is(x) insert(x)
#define sit set<int>::iterator
#define mapit map<int,int>::iterator
#define pi pair<int,int>
#define ppi pair<int,pi>
#define pp pair<pi,pi>
#define fr first
#define se second
#define vit vector<int>::iterator
#define mp(x,y) make_pair(x,y)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
using namespace std;
const int MAXN=5e4+10,mod=998244353;
ll n,c[MAXN],b[MAXN],m,fact[MAXN],inv[MAXN];
ll cnt[MAXN],g[MAXN],inv2[MAXN];
ll a[MAXN];
set<ll>s;
ll power(ll a,ll n){
	if(!n)return 1;
	ll tmp=power(a,n/2);tmp=tmp*tmp%mod;
	if(n&1)tmp=tmp*a%mod;return tmp;
}
il ll C(ll n,ll m){
	if(n<0 || m<0 || n<m)return 0;
	return fact[n]*inv[m]%mod*inv[n-m]%mod;
}
il ll calc(ll val,ll k){
	//当前元素val个,总共选k个
	ll ret=0;
	ret=(C(n,k)-C(n-val,k)+mod)%mod;
	ret=(ret*inv2[k])%mod;
	return ret; 
}
ll f(ll k){
	ll ret=0;
	rep(i,1,a[0]){
		ll val=a[i];
		ret=(ret+g[val]*calc(val,k)%mod)%mod;
	}
	return ret;
}
int main(){
	fact[0]=inv[0]=1;
	rep(i,1,5e4)fact[i]=fact[i-1]*i%mod;
	rep(i,1,5e4)inv[i]=power(fact[i],mod-2);
	scanf("%lld",&n);
	rep(i,1,5e4)inv2[i]=power(C(n,i)%mod,mod-2);
	rep(i,1,n){
		scanf("%lld",&c[i]);
		b[++m]=c[i];
	}
	sort(b+1,b+1+m);
	m=unique(b+1,b+1+m)-b-1;
	rep(i,1,n){
		c[i]=lower_bound(b+1,b+1+m,c[i])-b;
		cnt[c[i]]++;
	}
	rep(i,1,m){
		g[cnt[i]]++;
	}
	rep(i,1,n){
		if(g[i]==0)continue;
		a[++a[0]]=i;
	}
	rep(i,1,n){
		printf("%lld\n",f(i));
	}
	return 0;
}

posted on 2021-08-24 19:31  Cry_For_theMoon  阅读(104)  评论(0编辑  收藏  举报