【2022 省选训练赛 Contest 15 A】set(数学)(组合数)(二项式定理)

set

题目链接:2022 省选训练赛 Contest 15 A

题目大意

有 1~n 共 n 个数,然后问你随机选 k 个,其中设其最小值为 x,求 T^x 的期望值。

思路

首先显然列出一个式子(枚举哪个数作为最小值):
\(\dfrac{\sum\limits_{i=1}^nT^i\binom{n-i}{k-1}}{\binom{n}{k}}\)
然后下面先不管(反正可以 \(O(k)\) 求,就拆开来然后带有 \(n\) 的阶乘两个消),所以就考虑怎么求上面的。

先来看看代码的(猪鼻)推导。
\(1.\sum\limits_{i=1}^nT^i\binom{n-i}{k-1}\)
\(2.\sum\limits_{i=1}^n\sum\limits_{j=0}^i(T-1)^j\binom{i}{j}\binom{n-i}{k-1}\)(二项式定理)
\(3.\sum\limits_{j=0}^n(T-1)^j\sum\limits_{i=1}^n\binom{i}{j}\binom{n-i}{k-1}\)\(i\) 可以不从 \(i\) 开始因为前面的答案都是 \(0\)
\(4.\sum\limits_{j=0}^n(T-1)^j\sum\limits_{i=1}^n\binom{n+k}{j+k}\)(你可以理解为两个部分中间用一个选了的隔开,前面的选 \(j\) 个,后面的选 \(k-1\) 个)
\(5.T^{n+1}-\sum\limits_{j=0}^{k-1}\binom{n+1}{j}\)(把 \(T^{n+1}\) 二项式定理展开,然后容斥)
\(T^{n+1}=\sum\limits_{j=0}^{n+1}\binom{n+k}{j}(T-1)^j\)

首先发现一个显然的错误:
\(5\) 中应该是 \(T^{n+1}-\sum\limits_{j=0}^{k-1}\binom{n+1}{j}T^{j}\)
然后你再看会发现其实它还有错,就是 \(5\) 中应该整个式子除 \((T-1)^k\)
然后你按着写发现错了,然后你就检查式子。

然后你会发现 \(4\) 有个小小的问题,就是你组合数的话 \(i=0\) 的情况时要计算的,但是前面 \(3\)\(i\)\(1\sim n\)
不过你会发现好像 \(i=0\) 的时候后面的部分都是 \(0\),但你很快会发现有一个特别的情况就是 \(j=0\),这个时候后面的式子是 \(\binom{j}{i}\binom{n-i}{k-1}=\binom{0}{0}\binom{n-0}{k-1}=\binom{n}{k-1}\)

所以你应该要减去一个 \(\binom{n}{k-1}\),而且你要注意的是后面的部分,你都除了 \((T-1)^k\),而你这个是不能除的,所以如果你前面都除了你这个的减去就要乘 \((T-1)^k\)

然后就终于可以过了TAT

代码

#include<cstdio>
#define ll long long
#define mo 998244353

using namespace std;

ll n, k, t, inv[10000001], all;

ll ksm(ll x, ll y) {
	ll re = 1;
	while (y) {
		if (y & 1) re = re * x % mo;
		x = x * x % mo; y >>= 1;
	}
	return re;
}

int main() {
	scanf("%lld %lld %lld", &n, &k, &t);
	
	if (t == 1) {//特判
		printf("1"); return 0;
	}
	
	inv[0] = inv[1] = 1; for (int i = 2; i <= k; i++) inv[i] = inv[mo % i] * (mo - mo / i) % mo;
	
	all = 1;
	for (int i = 1; i <= k; i++) all = all * (n - i + 1) % mo * inv[i] % mo;
	
	ll ans = ksm(t, n + 1), sum = 1;
	for (ll i = 0; i < k; i++) {
		ans = (ans - sum + mo) % mo;
		sum = sum * (n + 1 - (i + 1) + 1) % mo * inv[i + 1] % mo;
		sum = sum * (t - 1) % mo;
	}
	ll mor = 1;
	for (ll i = 1; i <= k - 1; i++) mor = mor * (n - i + 1) % mo * inv[i] % mo;
	ans = (ans - mor * ksm(t - 1, k) % mo + mo) % mo;
	ans = ans * ksm(ksm(t - 1, k), mo - 2) % mo;
	printf("%lld", ans * ksm(all, mo - 2) % mo);
	
	return 0;
}
posted @ 2022-03-17 22:24  あおいSakura  阅读(34)  评论(0编辑  收藏  举报