5322: [Jxoi2018]排序问题
5322: [Jxoi2018]排序问题
分析:
每次选一个出现次数最小的。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> #define pa pair<int,int> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int mod = 998244353; int fac[10200005], a[200005], b[200005]; int ksm(int a,int b) { int res = 1; while (b) { if (b & 1) res = 1ll * res * a % mod; a = 1ll * a * a % mod; b >>= 1; } return res; } void solve() { int n = read(), m = read(), l = read(), r = read(), tot = 0, cnt = 0, f = r - l + 1, ans = 1; for (int i = 1; i <= n; ++i) a[i] = read(); sort(a + 1, a + n + 1); for (int i = 1, j = 1; i <= n; i = j) { while (j <= n && a[i] == a[j]) j ++; if (l <= a[i] && a[i] <= r) b[++tot] = j - i, f --; else ans = 1ll * ans * fac[j - i] % mod; } sort(b + 1, b + tot + 1); for (int i = 1, j = 1; i <= tot; i = j) { while (j <= tot && b[i] == b[j]) j ++; ++cnt; a[cnt] = b[i], b[cnt] = j - i; } a[++cnt] = 1e9, b[cnt] = 1; for (int i = 1, M = m; i <= cnt; ++i) { LL c = a[i] - a[i - 1], t = c * f; if (t > M) { int x = a[i - 1] + (M / f), y = M % f; ans = 1ll * ans * ksm(fac[x], f - y) % mod * ksm(fac[x + 1], y) % mod; for (int j = i; j < cnt; ++j) ans = 1ll * ans * ksm(fac[a[j]], b[j]) % mod; break; } M -= t, f += b[i]; } ans = 1ll * fac[n + m] * ksm(ans, mod - 2) % mod; printf("%d\n", ans); } int main() { fac[0] = 1; for (int i = 1; i <= 10200000; ++i) fac[i] = 1ll * fac[i - 1] * i % mod; for (int T = read(); T --; solve()); return 0; }