题解:P10986 [蓝桥杯 2023 国 Python A] 2023
二项式反演。
题目里有“恰好”的标志,套路的,我们可以将它转化为至多/至少后再容斥回来。
当我们已经确定
也就是说,在剩余的数随便选时,我们可能会多选若干个
很容易想到这可以转化成“至少”的形式。
那么问题就转化成了两部分:
-
随便选剩余的数。
-
由“至少”推向“恰好”。
我们先来看第一部分。
当确定
举个例子:
x2023x2023x2023x
其中 x 代表的是一堆随便选的数字。
这是个经典的隔板法,讲这些数字分到
又因为题目明示了我们前导零的合法,所以再乘上每个数都有的
第二部分,直接套公式即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6 + 5, N = 5e5 + 5, mod = 998244353;
int qpow(int b, int p) {
int res = 1;
while (p) {
if (p & 1) {
res = res * b % mod;
}
b = b * b % mod;
p >>= 1;
}
return res;
}
int n, k, fac[maxn], ifac[maxn], g[N];
inline void init() {
fac[0] = 1;
for (int i = 1; i <= N; i ++) {
fac[i] = fac[i - 1] * i % mod;
}
ifac[N] = qpow(fac[N], mod - 2);
for (int i = N - 1; ~i; i --) {
ifac[i] = ifac[i + 1] * (i + 1) % mod;
}
}
inline int C(int n, int m) {
if (n < m || n < 0 || m < 0) {
return 0;
} else {
return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
}
signed main() {
cin >> n >> k, init();
for(int m = k; m <= n / 4; m ++) {
int p = n - 4 * m;
g[m] = C(p + m, m) * qpow(10, p) % mod;
}
int ans = 0;
for(int i = n / 4; i >= k; i --) {
if(i - k & 1) ans = (ans - C(i, k) * g[i] % mod + mod) % mod;
else ans = (ans + C(i, k) * g[i] % mod) % mod;
}
cout << ans << '\n';
return 0;
}