【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;
}