CF1445D Divide and Sum
阿新 • • 發佈:2020-11-01
一個水題,但是考場上愣是想了半個小時,最後忘了加模數再取模導致我fst。
考慮 \(\mid x_i - y_i \mid\) 的意義,就是 \(\max(x_i, y_i) - \min(x_i, y_i)\) 那麼就是說對於每個位置,取兩個排列中的最大值減去最小值。
這樣的排列一共會有 \(C_{2n}^n\) 個。
這裡先給出一個結論,排序後,後半部分永遠會被取成最大值,前半部分永遠會被取成最小值。
(以下內容均以排序後的原陣列為準)
上述結論是由其排列排列順序決定的,考慮後半部分的數如果放到 \(p\) 中,那麼一定在最後幾個。如果放到 \(q\) 中,一定在前幾個,那麼我們可以知道原序列的一半恰好等於 \(p, q\)
所以答案即為排序後的陣列 \(\displaystyle \Big( \sum_{i=n+1}^{2\cdot n} a_i - \sum_{i=1}^n a_i \Big) \cdot C_{2n}^n\)。
我比較菜,寫的線性求逆元+階乘。
時間複雜度 \(O(n)\),空間複雜度 \(O(n)\)。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long ll; const ll MAXN = 1e6+10, MOD = 998244353; ll N, M, fac[MAXN], val[MAXN], inv[MAXN], ans; int main() { scanf("%lld", &N); inv[1] = inv[0] = fac[1] = fac[0] = 1; for (ll i = 2; i <= N<<1; i++) fac[i] = fac[i-1] * i % MOD, inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD; for (ll i = 1; i <= N<<1; i++) inv[i] = inv[i-1] * inv[i] % MOD; for (ll i = 1; i <= N<<1; i++) scanf("%lld", val+i); ll tem = fac[N<<1] * inv[N] % MOD * inv[N] % MOD; sort(val+1, val+(N<<1)+1); for (ll i = 1; i <= N; i++) ans = (ans - tem * val[i] % MOD) % MOD; for (ll i = N + 1, k = N << 1; i <= k; i++) ans = (ans + tem * val[i] % MOD) % MOD; printf("%lld\n", (ans + MOD) % MOD); return 0; }