【CF891E】Lust 生成函数

【CF891E】Lust

题意:给你一个长度为n的序列$a_i$,对这个序列进行k次操作,每次随机选择一个1到n的数x,令$res+=\prod\limits_{i!=x}a_i$(一开始res=0),然后$a_i$--。问最终res的期望值。答案在模意义下对$10^9+7$取模。

$n\le 5000,k\le 10^9$

题解:首先需要发现,假如第i个数被减的次数为$b_i$,则$res=\prod\limits_i a_i-\prod\limits_i (a_i-b_i)$。这个用归纳法容易证明。

于是问题就变成了求$[{\sum b_i=k}]{1\over n^k}{k!\over \prod b_i!}\prod\limits_{i}(a_i-b_i)$

设生成函数$F_i(x)=\sum\limits_{j}{(a_i-j)x^j\over j!}$,它等于

$F_i(x)=\sum\limits_j{a_ix^j\over j!}-\sum\limits_j{x^j\over (j-1)!}\\=\sum\limits_{j}{a_ix^j\over j!}-x\sum\limits_{j}{x^j\over j!}\\=\sum\limits_j{(a_i-x)x^j\over j!}=(a_i-x)e^j$

所以$\prod\limits_i F_i(x)=e^{nj}\prod\limits_i (a_i-x)$。我们可以暴力求出$\prod\limits_i (a_i-x)$的每一项系数,设其为$c_i$。剩下的就是求$e^{nj}$的第$k-n,k-n+1...k$项系数。显然第i项系数是$n^i\over i!$,再乘上前面的${k!\over n^k}$就变成了$\sum\limits_{i=0}^n{c_i}n^{-i}\prod\limits_{j=k-i}^kj$

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=5010;
typedef long long ll;
const ll P=1000000007;
ll ine[maxn],v[maxn],f[maxn];
int n;
ll k,ans;
int main()
{
	int i,j;
	scanf("%d%lld",&n,&k);
	for(ans=i=1;i<=n;i++)	scanf("%lld",&v[i]),ans=ans*v[i]%P;
	f[0]=1;
	for(i=1;i<=n;i++)
	{
		for(j=i;j>=1;j--)
		{
			f[j]=(f[j]*v[i]-f[j-1])%P;
		}
		f[0]=f[0]*v[i]%P;
	}
	ine[0]=ine[1]=1;
	for(i=2;i<=n;i++)	ine[i]=P-(P/i)*ine[P%i]%P;
	ll t=1,tmp=1;
	for(i=0;i<=n&&i<=k;i++)
	{
		ans=(ans-f[i]*t%P*tmp)%P;
		t=t*ine[n]%P,tmp=tmp*(k-i)%P;
	}
	printf("%lld",(ans+P)%P);
	return 0;
}
posted @ 2018-03-18 12:16  CQzhangyu  阅读(840)  评论(0编辑  收藏  举报