题解 CF891E Lust

题意

你有 \(n\) 个数 \(a_1,a_2,\dots,a_n\),要进行 \(k\) 次操作,每次随机选择一个数 \(x\in[1,n]\),把 \(a_x\) 减一,并将答案增加除 \(a_x\) 外所有数的乘积。

求最终答案的期望,答案对 \(10^9+7\) 取模。

解法

对于任意两次相邻的操作,将其交换后对答案并不影响,因此最终答案和每次减 \(1\)\(a_i\) 的顺序无关,只和每个 \(a_i\) 被减了多少有关。

\(a_i\) 最终减少了 \(b_i\),容易发现题目要求的即为 \(\prod_{i=1}^{n}a_i-\prod_{i=1}^{n}(a_i-b_i)\) 的期望,因此我们只需求出 \(Res=\prod_{i=1}^{n}(a_i-b_i)\) 的期望。

注意到 \(Res=E(\prod_{i=1}^{n}(a_i-b_i))=\dfrac{1}{n^k}\sum\dfrac{k!}{\prod_{i=1}^{n}b_i!}\prod_{i=1}^{n}(a_i-b_i)=\dfrac{k!}{n^k}\sum\prod_{i=1}^{n}\dfrac{a_i-b_i}{b_i!}\),这和指数生成函数的形式很像,因此我们考虑每一个 \(a_j\) 的指数生成函数 \(\hat{F}_j(x)=\sum_{i\ge0}\dfrac{a_j-i}{i!}x^i\),则 \(\dfrac{k!}{n^k}\sum\prod_{i=1}^{n}\dfrac{a_i-b_i}{b_i!}=\dfrac{k!}{n^k}[x^k]\prod_{i=1}^{n}\hat{F}_i(x)\)

\(\hat{F}_j(x)=\sum_{i\ge0}\dfrac{a_j-i}{i!}x^i\)

\(=\sum_{i\ge0}{\dfrac{a_jx^i}{i!}}-\sum_{i\ge0}{\dfrac{ix^i}{i!}}\)

\(=\sum_{i\ge0}{\dfrac{a_jx^i}{i!}}-\sum_{i\ge1}{\dfrac{xx^{i-1}}{(i-1)!}}\)

\(=\sum_{i\ge0}{\dfrac{(a_j-x)x^i}{i!}}\)

\(=e^x(a_j-x)\)

所以 \(Res=\dfrac{k!}{n^k}[x^k]\prod_{i=1}^{n}e^x(a_j-x)\)

\(=\dfrac{k!}{n^k}[x^k]e^{nx}\prod_{i=1}^{n}(a_j-x)\)

\(=\dfrac{k!}{n^k}[x^k]\sum_{i\ge0}{\dfrac{n^i}{i!}}x^i\prod_{i=1}^{n}(a_j-x)\)

由于 \(n\le5000\),我们暴力展开 \(\prod_{i=1}^{n}(a_j-x)=\sum_{i=0}^{n}c_ix^i\)

所以 \(Res=\dfrac{k!}{n^k}[x^k]\sum_{i\ge0}{\dfrac{n^i}{i!}}x^i\sum_{i=0}^{n}c_ix^i\)

\(=\dfrac{k!}{n^k}\sum_{i=0}^{\min(n,k)}\dfrac{c_in^{k-i}}{(k-i)!}\)

\(=c_0+\sum_{i=1}^{\min(n,k)}\dfrac{c_i\prod_{j=k-i+1}^{k}j}{n^i}\)

最终答案为 \(\prod_{i=1}^{n}a_i-Res=-\sum_{i=1}^{\min(n,k)}\dfrac{c_i\prod_{j=k-i+1}^{k}j}{n^i}\),时间复杂度 \(O(n^2)\)

Code

#include<cstdio>
#define LL long long
#define mod 1000000007
int n,k,e;LL t,ans=0,res,inv,mul=1;
LL a[5002],c[5002]={};
inline int min(int x,int y)
{
	return x<y? x:y;
}
inline LL pow(LL a,int b)
{
	if(!b)return 1;
	if(b==1)return a;
	LL c=pow(a,(b>>1));
	c=(c*c)%mod;
	if(b&1)c=(c*a)%mod;
	return c;
}
int main()
{
	scanf("%d%d",&n,&k),e=min(n,k),t=inv=pow(n,mod-2),c[n]=1;
	for(int i=1;i<=n;++i)
	{
		scanf("%lld",&a[i]);
		for(int j=n-i;j<n;++j)c[j]=(c[j+1]*a[i]-c[j])%mod;
		c[n]=-c[n];
	}
	for(int i=1;i<=e;++i,t=(t*inv)%mod)
	{
		res=t;
		for(int j=k-i+1;j<=k;++j)res=(res*j)%mod;
		ans=(ans-c[i]*res)%mod;
	}
	printf("%lld",(ans+mod)%mod);
	return 0;
}
posted @ 2021-03-31 19:21  18Michael  阅读(89)  评论(0编辑  收藏  举报