【CF891E】Lust 生成函数
【CF891E】Lust
题意:给你一个长度为n的序列ai,对这个序列进行k次操作,每次随机选择一个1到n的数x,令res+=∏i!=xai(一开始res=0),然后ai--。问最终res的期望值。答案在模意义下对109+7取模。
n≤5000,k≤109
题解:首先需要发现,假如第i个数被减的次数为bi,则res=∏iai−∏i(ai−bi)。这个用归纳法容易证明。
于是问题就变成了求[∑bi=k]1nkk!∏bi!∏i(ai−bi)
设生成函数Fi(x)=∑j(ai−j)xjj!,它等于
Fi(x)=∑jaixjj!−∑jxj(j−1)!=∑jaixjj!−x∑jxjj!=∑j(ai−x)xjj!=(ai−x)ej
所以∏iFi(x)=enj∏i(ai−x)。我们可以暴力求出∏i(ai−x)的每一项系数,设其为ci。剩下的就是求enj的第k−n,k−n+1...k项系数。显然第i项系数是nii!,再乘上前面的k!nk就变成了n∑i=0cin−ik∏j=k−ij
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #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; } |
| 欢迎来原网站坐坐! >原文链接<
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步