[CodeForces891E]Lust-生成函数-概率与期望

Lust

A false witness that speaketh lies!

You are given a sequence containing n integers. There is a variable res that is equal to 0 initially. The following process repeats k times.

Choose an index from 1 to n uniformly at random. Name it x. Add to res the multiply of all ai’s such that 1 ≤ i ≤ n, but i ≠ x. Then, subtract ax by 1.

You have to find expected value of res at the end of the process. It can be proved that the expected value of res can be represented as an irreducible fraction . You have to find .

Input

The first line contains two integers n and k (1 ≤ n ≤ 5000, 1 ≤ k ≤ 109) — the number of elements and parameter k that is specified in the statement.

The second line contains n space separated integers a1, a2, …, an (0 ≤ ai ≤ 109).

Output

Output a single integer — the value .

Examples

input

2 1
5 5

output

5

input

1 10
80

output

10

input

2 2
0 0

output

500000003

input

9 4
0 11 12 9 20 7 8 18 2

output

169316356

一道神题……
太弱导致看着题解都推了好久……


思路:

首先,假如现在已经得到了某个操作序列,设 ai 被操作的次数为 bi ,那么它对期望值的贡献为:

cont=i=1naii=1n(aibi)

可以发现这是顺序无关的~

于是可以得到计算答案的式子:

ans=i=1naini=1bi==k1nkk!ni=1bi!i=1n(aibi)

其中, k!ni=1bi! 是不全相异元素的选排列公式。

前半部分由于过于简单暂不考虑,于是考虑化简后半部分,即:

ni=1bi==k1nkk!ni=1bi!i=1n(aibi)

简单化简一下:

k!nkni=1bi==ki=1naibibi!

考虑写出求和符号及其后方内容的生成函数:

F(x)=i=1nj0aijj!xj

F(x) 的第 k 项即为所求的答案。

观察求和符号,可以发现它很像 ex 的泰勒展开形式,于是有:

F(x)=i=1nex(aix)

稍微化简:

F(x)=enxi=1n(aix)

考虑对连乘符号后的式子进行 O(n2) 暴力多项式乘法求系数。(这步显然可以分治FFT)
于是设 i=0ncixi=i=1n(aix) ,其中 ci 为求得的系数,那么有:

F(x)=enxi=0ncixi

enx 重新泰勒展开,与刚才得到的多项式相乘,得到 F(x) k 次项系数的表达式:

[xk]F(x)=i=0ncinki(ki)!

回带到原式中,有:

ans=i=1naik!nki=0ncinki(ki)!

进行化简,得到最终的式子:

ans=i=1naii=0ncikini

O(n) 计算这个式子即可~

总复杂度 O(n2) ,瓶颈在于那个可以用分治FFT优化的地方~
也就是说这题可以换个模数或者干脆不换以出到更大的范围~

#include
using namespace std;

typedef long long ll;
const ll md=1e9+7;
const int N=5009;

int n,k,m;
ll a[N],b[N],c[N];

inline ll read()
{
    ll x=0;char ch=getchar();
    while(ch<'0' || '9'while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
    return x;
}

inline ll qpow(ll a,ll b)
{
    ll ret=1;
    while(b)
    {
        if(b&1)ret=ret*a%md;
        a=a*a%md;b>>=1;
    }
    return ret;
}

inline int mult(ll *a,int n,ll *b,int m,ll *c)
{
    static ll d[N];
    memset(d,0,sizeof(d[0])*(n+m+5));
    for(int i=0;ifor(int j=0;jfor(int i=0;i1;i++)
        c[i]=d[i]%md;
    return n+m-1;
}

int main()
{
    n=read();k=read();
    for(int i=1;i<=n;i++)
        a[i]=read();

    c[0]=1;m=1;
    for(int i=1;i<=n;i++)
    {
        b[0]=a[i];b[1]=-1;
        m=mult(b,2,c,m,c);
    }

    ll ans=1,powk=1;
    ll invn=qpow(n,md-2),inv=1;
    for(int i=1;i<=n;i++)
        ans=ans*a[i]%md;
    for(int i=0;i<=n && i<=k;i++)
    {
        ans=(ans-c[i]*powk%md*inv%md+md)%md;
        powk=powk*(k-i)%md;inv=inv*invn%md;
    }

    printf("%I64d\n",ans);
    return 0;
}

你可能感兴趣的:(生成函数【Generation,Function】,Theory】)