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;
}
posted @ 2020-11-16 23:05  With_penguin  阅读(60)  评论(0编辑  收藏  举报