CF891E Lust
发现一次改变带来的收益就是 \(\prod a_i-\prod a_i'\)(\(a_i'\) 表示改变后的 \(a\) 数列)。所以最后就是求 \(\prod a_i-\prod(a_i-b_i)\)(其中 \(\sum b_i=k\))的期望。
考虑计算 \(\sum\prod(a_i-b_i)\)。发现就是求 \([x^n]\prod\sum\limits_{j = 1}^n (a_i - j)\)。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
typedef unsigned long long uLL;
typedef long long LL;
typedef vector <int> Poly;
const int M = 1000000007, g = 3, N = 4200009, K = 4200000;
int max_len, max_L, rev[N], W[N], n, k, a[N], fac[N], inv_fac[N];
Poly A, B;
int ksm(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1)
res = 1ll * res * a % M;
b >>= 1, a = 1ll * a * a % M;
}
return res;
}
int invs(int x) { return ksm(x, M - 2); }
void prework()
{
max_len = 1 << 22, max_L = 22;
for (int i = 1; i <= max_len; i++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << max_L - 1);
W[max_len >> 1] = 1;
int wn = ksm(g, (M - 1) / max_len);
for (int i = (max_len >> 1) + 1; i < max_len; i++)
W[i] = 1ll * W[i - 1] * wn % M;
for (int i = (max_len >> 1) - 1; i; i--)
W[i] = W[i << 1];
fac[0] = 1;
for (int i = 1; i <= K; i++)
fac[i] = 1ll * fac[i - 1] * i % M;
inv_fac[K] = ksm(fac[K], M - 2);
for (int i = K - 1; i >= 0; i--)
inv_fac[i] = 1ll * inv_fac[i + 1] * (i + 1) % M;
}
Poly operator * (Poly A, Poly B)
{
int deg = A.size() + B.size() - 1;
Poly C; C.resize(deg);
for (int i = 0; i < A.size(); i++)
for (int j = 0; j < B.size(); j++)
C[i + j] = (C[i + j] + 1ll * A[i] * B[j] % M) % M;
return C;
}
Poly cdq_NTT(int l, int r)
{
if (l == r)
return Poly {a[l], M - 1};
int mid = l + r >> 1;
return cdq_NTT(l, mid) * cdq_NTT(mid + 1, r);
}
void init()
{
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
}
void work()
{
Poly tmp = cdq_NTT(1, n);
int prod = 1, res = 0, p = ksm(n, k), invn = ksm(n, M - 2);
for (int i = 1; i <= n; i++)
prod = 1ll * a[i] * prod % M;
for (int i = 0, j = p, x = 1; i <= min(n, k); x = 1ll * x * (k - i) % M, i++, j = 1ll * j * invn % M)
res = (res + 1ll * tmp[i] * j % M * x % M) % M;
printf("%lld\n", (prod + M - 1ll * res * invs(p) % M) % M);
}
int main()
{
prework();
init();
work();
return 0;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!