题目
你有n个数
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an ,要进行
k
k
k 次操作,每次在
1
1
1 ~
n
n
n 中随机选择一个数
x
x
x,使得
r
e
s
+
=
∏
i
!
=
x
a
i
res+=\prod_{i!= x}a_i
res+=∏i!=xai ,然后
a
x
a_x
ax 减少
1
1
1,求最后
r
e
s
res
res 值的期望,答案对
1
0
9
+
7
10^9+7
109+7 取模。
数据范围:
1
≤
n
≤
5000
,
1
≤
k
≤
1
0
9
,
0
≤
a
i
≤
1
0
9
1\le n\le 5000,1\le k \le 10^9,0\le a_i\le 10^9
1≤n≤5000,1≤k≤109,0≤ai≤109
思路
我们考虑在某一个局面即将进行一次操作:
记现在
a
i
a_i
ai 减少的次数为
b
i
b_i
bi ,我们选中
a
x
a_x
ax
那我们计算一次答案贡献:
∏
i
!
=
x
(
a
i
−
b
i
)
,
同
时
b
x
+
=
1
\prod_{i!=x}(a_i-b_i),同时b_x+=1
i!=x∏(ai−bi),同时bx+=1
那么我们变形
(
(
a
x
−
b
x
)
−
(
a
x
−
(
b
x
+
1
)
)
)
∗
∏
i
!
=
x
(
a
i
−
b
i
)
((a_x-b_x)-(a_x-(b_x+1)))*\prod_{i!=x}(a_i-b_i)
((ax−bx)−(ax−(bx+1)))∗i!=x∏(ai−bi)
∏
i
=
1
n
(
a
i
−
b
i
)
−
(
∏
i
=
1
n
(
a
i
−
b
i
)
)
∗
(
a
x
−
(
b
x
+
1
)
)
\prod_{i=1}^n(a_i-b_i)-(\prod_{i=1}^n(a_i-b_i))*(a_x-(b_x+1))
i=1∏n(ai−bi)−(i=1∏n(ai−bi))∗(ax−(bx+1))
我们记某一个局面
α
=
(
b
1
,
b
2
,
.
.
.
,
b
n
)
\alpha=(b_1,b_2,...,b_n)
α=(b1,b2,...,bn)
我们记
f
(
α
)
=
∏
i
=
1
n
(
a
i
−
b
i
)
f(\alpha)=\prod_{i=1}^n(a_i-b_i)
f(α)=i=1∏n(ai−bi)
那么一次的贡献为:
f
(
α
)
−
f
(
β
)
f(\alpha)-f(\beta)
f(α)−f(β)
初局面:
f
(
s
t
a
r
t
)
=
∏
i
=
1
n
a
i
f(start)=\prod_{i=1}^na_i
f(start)=i=1∏nai
于是类似于裂项相消的样子,我们只剩初局面和末局面
即
E
=
f
(
s
t
a
r
t
)
−
∑
k
!
n
k
∗
∏
i
=
1
n
b
i
!
∗
f
(
e
n
d
)
E=f(start)-\sum\frac{k!}{n^k*\prod_{i=1}^nb_i!}* f(end)
E=f(start)−∑nk∗∏i=1nbi!k!∗f(end)
于是我们只需保证:
∑
i
=
1
n
b
i
=
k
\sum_{i=1}^nb_i=k
∑i=1nbi=k,
化简后半段
∑
k
!
n
k
∗
∏
i
=
1
n
b
i
!
∗
∏
i
=
1
(
a
i
−
b
i
)
=
k
!
n
k
∗
∑
∏
i
=
1
a
i
−
b
i
b
i
!
\sum\frac{k!}{n^k*\prod_{i=1}^nb_i!}*\prod_{i=1}(a_i-b_i)=\frac{k!}{n^k}*\sum\prod_{i=1}\frac{a_i-b_i}{b_i!}
∑nk∗∏i=1nbi!k!∗i=1∏(ai−bi)=nkk!∗∑i=1∏bi!ai−bi
发现这个似乎很难搞,我们考虑化简和指数型母函数构造:
G
(
x
)
=
∏
i
=
1
n
∑
j
=
0
+
∞
a
i
−
j
j
!
x
j
G(x)=\prod_{i=1}^n\sum_{j=0}^{+\infty}\frac{a_i-j}{j!}x^j
G(x)=i=1∏nj=0∑+∞j!ai−jxj
=
∏
i
=
1
n
∑
j
=
0
+
∞
(
a
i
j
!
x
j
−
j
j
!
x
j
)
=\prod_{i=1}^n\sum_{j=0}^{+\infty}(\frac{a_i}{j!}x^j-\frac{j}{j!}x^j)
=i=1∏nj=0∑+∞(j!aixj−j!jxj)
=
∏
i
=
1
n
(
∑
j
=
0
+
∞
a
i
j
!
x
j
−
∑
j
=
0
+
∞
x
j
!
x
j
)
=\prod_{i=1}^n(\sum_{j=0}^{+\infty}\frac{a_i}{j!}x^j-\sum_{j=0}^{+\infty}\frac{x}{j!}x^j)
=i=1∏n(j=0∑+∞j!aixj−j=0∑+∞j!xxj)
=
∏
i
=
1
n
(
(
a
i
−
x
)
∗
∑
j
=
0
+
∞
x
j
j
!
)
=\prod_{i=1}^n((a_i-x)*\sum_{j=0}^{+\infty}\frac{x^j}{j!})
=i=1∏n((ai−x)∗j=0∑+∞j!xj)
=
∏
i
=
1
n
(
(
a
i
−
x
)
∗
e
x
)
=\prod_{i=1}^n((a_i-x)*e^x)
=i=1∏n((ai−x)∗ex)
=
e
n
x
∏
i
=
1
n
(
a
i
−
x
)
=e^{nx}\prod_{i=1}^n(a_i-x)
=enxi=1∏n(ai−x)
我们的目标是求
G
(
x
)
G(x)
G(x) 的第
k
k
k 项系数
f
k
f_k
fk,考虑将后面直接
O
(
n
2
)
O(n^2)
O(n2) 拆成多项式形式(当然你会分治FFT
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)):
G
(
x
)
=
e
n
x
∗
∑
i
=
0
n
c
i
∗
x
i
G(x)=e^{nx}*\sum_{i=0}^nc_i*x^i
G(x)=enx∗i=0∑nci∗xi
前面拆开:
G
(
x
)
=
(
1
+
n
x
1
!
+
(
n
x
)
2
2
!
+
.
.
.
)
∗
∑
i
=
0
n
c
i
∗
x
i
G(x)=(1+\frac{nx}{1!}+\frac{(nx)^2}{2!}+...)*\sum_{i=0}^nc_i*x^i
G(x)=(1+1!nx+2!(nx)2+...)∗i=0∑nci∗xi
我们要求第
k
k
k 项的系数
g
k
g_k
gk:
g
k
=
∑
i
=
0
n
c
i
∗
n
k
−
i
(
k
−
i
)
!
g_k=\sum_{i=0}^nc_i*\frac{n^{k-i}}{(k-i)!}
gk=i=0∑nci∗(k−i)!nk−i
回代到答案的后半段:
k
!
n
k
∗
∑
∏
i
=
1
a
i
−
b
i
b
i
!
=
k
!
n
k
∗
g
k
\frac{k!}{n^k}*\sum\prod_{i=1}\frac{a_i-b_i}{b_i!}=\frac{k!}{n^k}*g_k
nkk!∗∑i=1∏bi!ai−bi=nkk!∗gk
=
k
!
n
k
∗
∑
i
=
0
n
c
i
∗
n
k
−
i
(
k
−
i
)
!
=\frac{k!}{n^k}*\sum_{i=0}^nc_i*\frac{n^{k-i}}{(k-i)!}
=nkk!∗i=0∑nci∗(k−i)!nk−i
我们知道
n
n
n 相较于
k
k
k 很小 于是继续化简:
=
∑
i
=
0
n
c
i
∗
A
k
i
n
i
=\sum_{i=0}^nc_i*\frac{A_k^i}{n^i}
=i=0∑nci∗niAki
最后这个式子我们可以考虑递推
O
(
n
)
O(n)
O(n) 计算
总时间复杂度:
O
(
n
2
)
/
O
(
n
l
o
g
2
n
)
O(n^2)/O(nlog^2n)
O(n2)/O(nlog2n)
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<ctime>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
LL read(){
LL f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return f*x;
}
#define MAXN 5000
#define INF 0x3f3f3f3f
#define Mod (LL)(1e9+7)
LL Pow(LL x,LL y){
LL ret=1;
while(y){
if(y&1) ret=ret*x%Mod;
x=x*x%Mod;
y>>=1;
}
return ret;
}
LL a[MAXN+5],b[MAXN+5],c[MAXN+5];
int main(){
LL n=read(),k=read(),ans=1;
for(int i=1;i<=n;i++)
a[i]=read(),ans=ans*a[i]%Mod;
c[0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<i;j++)
b[j]=c[j]*a[i]%Mod;
for(int j=0;j<i;j++)
b[j+1]=(b[j+1]-c[j]+Mod)%Mod;
memcpy(c,b,sizeof(c));
}
LL f=0,t1=1,t2=1,invn=Pow(n,Mod-2);
for(int i=0;i<=n;i++){
f=(f+c[i]*t1%Mod*t2%Mod)%Mod;
t1=t1*(k-i)%Mod,t2=t2*invn%Mod;
}
ans=(ans-f)%Mod;
printf("%lld\n",(ans+Mod)%Mod);
return 0;
}