解题思路
这么水的题竟然没有大佬交题解…
首先, ∵ ∣ S ∣ ∉ S , ∣ T ∣ ∉ T ∴ ∣ S ∣ ∈ T , ∣ T ∣ ∈ S \because |S| \notin S, |T| \notin T \therefore |S| \in T, |T| \in S ∵∣S∣∈/S,∣T∣∈/T∴∣S∣∈T,∣T∣∈S。
确定了这两个值在哪边,其余 n − 2 n-2 n−2 个排在哪边都无所谓了,有 2 n − 2 2^{n-2} 2n−2 种方法。
注意一个值不能同时在 S S S 和 T T T 中,则 ∣ S ∣ ≠ ∣ T ∣ |S| \ne |T| ∣S∣=∣T∣。这种情况只会在 n n n 为偶数时发生,所以此时的总方案数应该减去从 n − 2 n-2 n−2 个数中选出一半放在 S S S 中的数量,即 C n − 2 ( n − 2 ) / 2 C_{n-2}^{(n-2)/2} Cn−2(n−2)/2。
最后注意的是 n = 1 n=1 n=1 时需要特判,因为根本没有 ∣ S ∣ |S| ∣S∣ 和 ∣ T ∣ |T| ∣T∣ 两个值。
代码实现
组合数取模用了一点 L u c a s Lucas Lucas。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int P = 998244353;
int qpow(int x, int y) {
int res = 1;
while (y) {
if (y & 1) {
(res *= x) %= P;
}
(x *= x) %= P;
y >>= 1;
}
return res;
}
int C(int n, int m) {
int a = 1, b = 1;
for (int i = 1; i <= m; ++i) {
(a *= i) %= P;
(b *= n - i + 1) %= P;
}
return b * qpow(a, P - 2) % P;
}
int Lucas(int n, int m) {
return !m ? 1 : C(n % P, m % P) * Lucas(n / P, m / P) % P;
}
signed main() {
ios :: sync_with_stdio(0);
int n;
cin >> n;
if (n == 1) {
cout << 0 << '\n';
return 0;
}
int res = qpow(2, n - 2);
if (!(n & 1)) {
(res -= Lucas(n - 2, n - 2 >> 1) - P) %= P;
}
cout << res << '\n';
return 0;
}
Good Good 贺题,Day Day Up!!