Description
给出一长度为nn的序列,每次操作等概率的从11~中选一个数xx,把这个数去掉axax后的乘积加到答案里,然后把axax减一,问kk次操作后答案的期望值
Input
第一行输入两个整数,之后输入nn个整数
Output
保证答案可以写成最简分数形式PQPQ,输出P⋅Q−1 mod109+7P⋅Q−1 mod109+7
Sample Input
2 1
5 5
Sample Output
5
Solution
假设某次操作前这nn个数字变成,bibi为ii被选中的次数
当前操作选中了,那么该次操作的贡献为∏i≠x(ai−bi)=∏i=1n(ai−bi)−(ai−(bi+1))∏i≠x(ai−bi)∏i≠x(ai−bi)=∏i=1n(ai−bi)−(ai−(bi+1))∏i≠x(ai−bi)
不妨设ci=bi,i≠x,cx=bx+1ci=bi,i≠x,cx=bx+1为该次操作结束后ii被选中的次数
那么本次操作的贡献可以写成:
计算该交错和得总贡献为∏i=1nai−∏i=1n(ai−bi)∏i=1nai−∏i=1n(ai−bi),其中bibi为kk次操作后被选中的次数,∑i=1nbi=k∑i=1nbi=k
故答案的期望值为1nk∑∑i=1nbi=kk!∏i=1nbi!(∏i=1nai−∏i=1n(ai−bi))=∏i=1nai−k!nk∑∑i=1nbi=k∏i=1nai−bibi!1nk∑∑i=1nbi=kk!∏i=1nbi!(∏i=1nai−∏i=1n(ai−bi))=∏i=1nai−k!nk∑∑i=1nbi=k∏i=1nai−bibi!
令Pj(x)Pj(x)为上述求和式中第jj项对答案的贡献,则有
化简得Pj(x)=aj∑i≥01i!xi−x∑i≥11(i−1)!xi−1=(aj−x)⋅exPj(x)=aj∑i≥01i!xi−x∑i≥11(i−1)!xi−1=(aj−x)⋅ex
记f(k)=∑∑i=1nbi=k∏i=1nai−bibi!f(k)=∑∑i=1nbi=k∏i=1nai−bibi!,考虑其生成函数F(x)=∑i≥0f(i)⋅xiF(x)=∑i≥0f(i)⋅xi
有F(x)=∏j=1nPj(x)=enx⋅∏j=1n(aj−x)=enx⋅G(x)F(x)=∏j=1nPj(x)=enx⋅∏j=1n(aj−x)=enx⋅G(x)
O(n2)O(n2)直接计算得G(x)=∑i=0ngi⋅xiG(x)=∑i=0ngi⋅xi,进而有:
f(k)=[xk]F(x)=∑i=0min(n,k)[xi]G(x)⋅[xk−i]enx=∑i=0min(n,k)gi⋅nk−i(k−i)!f(k)=[xk]F(x)=∑i=0min(n,k)[xi]G(x)⋅[xk−i]enx=∑i=0min(n,k)gi⋅nk−i(k−i)!
故答案为∏i=1nai−k!nkf(k)=∏i=1nai−∑i=0min(n,k)gi⋅∏j=k−i+1kjni∏i=1nai−k!nkf(k)=∏i=1nai−∑i=0min(n,k)gi⋅∏j=k−i+1kjni
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=5005;
#define mod 1000000007
int n,k,v[maxn],a[maxn],b[maxn];
void inc(int &x,int y)
{
x=x+y>=mod?x+y-mod:x+y;
}
void dec(int &x,int y)
{
x=x-y<0?x-y+mod:x-y;
}
int Pow(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)ans=(ll)ans*a%mod;
a=(ll)a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
int ans=1;
for(int i=1;i<=n;i++)scanf("%d",&v[i]),ans=(ll)ans*v[i]%mod;
a[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<i;j++)
{
inc(b[j],(ll)v[i]*a[j]%mod);
dec(b[j+1],a[j]);
}
for(int j=0;j<=i;j++)a[j]=b[j],b[j]=0;
}
int m=min(n,k),p=1,q=1,inv=Pow(n,mod-2);
for(int i=0;i<=m;i++)
{
dec(ans,(ll)p*a[i]%mod*q%mod);
p=(ll)p*(k-i)%mod;
q=(ll)q*inv%mod;
}
printf("%d\n",ans);
}
return 0;
}