LOJ#3119 随机立方体
解:极大值至少为1。我们尝试把最大那个数的影响去掉。
最大那个数所在的一层(指一个三维十字架)都是不可能成为最大值的。
考虑容斥。我们试图求除了最大值以外至少有k个极大值的概率。
我们钦定某k个位置是极大值,且钦定顺序。这样的方案数有ni↓mi↓Li↓种。
考虑每种方案的概率。从小到大考虑,对于最小的那个极大值,如果是极大值,就要大于一个三维十字架中的所有数,这样的概率是1 / 集合大小。
对于次小极大值,它要大于自己的三维十字架和最小值的三维十字架的并。概率还是1 / 集合大小。
于是依次考虑完每个极大值,把概率求积即可。容斥的时候记得乘组合数。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 5 const int MO = 998244353, N = 5000010; 6 7 int n, m, K, L; 8 int fac[N], inv[N], invn[N]; 9 10 inline int qpow(int a, int b) { 11 int ans = 1; 12 while(b) { 13 if(b & 1) ans = 1ll * ans * a % MO; 14 a = 1ll * a * a % MO; 15 b = b >> 1; 16 } 17 return ans; 18 } 19 inline int Inv(int x) { 20 if(x < N) return inv[x]; 21 return qpow(x, MO - 2); 22 } 23 inline int C(int n, int m) { 24 return 1ll * fac[n] * invn[m] % MO * invn[n - m] % MO; 25 } 26 inline int Down(int n, int k) { 27 return 1ll * fac[n] * invn[n - k] % MO; 28 } 29 inline int iDown(int n, int k) { 30 return 1ll * invn[n] * fac[n - k] % MO; 31 } 32 inline int dec(int x) { 33 return 1ll * (n - x) * (m - x) % MO * (L - x) % MO; 34 } 35 36 inline void solve() { 37 38 scanf("%d%d%d%d", &n, &m, &L, &K); 39 int ans = 0, lm = std::min(std::min(n, m), L); 40 int V = 1ll * n * m % MO * L % MO; 41 for(int i = K - 1; i <= lm; i++) { 42 int p = 1; 43 for(int j = 1; j <= i; j++) { 44 p = 1ll * p * (n - i + j - 1) % MO * (m - i + j - 1) % MO * (L - i + j - 1) % MO; 45 p = 1ll * Inv((V - dec(j) + MO) % MO) * p % MO; 46 } 47 p = 1ll * p * C(i, K - 1) % MO; 48 if((K - i) & 1) { 49 ans = (ans + p) % MO; 50 } 51 else { 52 ans = (ans - p) % MO; 53 } 54 } 55 printf("%d\n", (ans + MO) % MO); 56 return; 57 } 58 59 int main() { 60 61 fac[0] = inv[0] = invn[0] = 1; 62 fac[1] = inv[1] = invn[1] = 1; 63 for(int i = 2; i < N; i++) { 64 fac[i] = 1ll * i * fac[i - 1] % MO; 65 inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO; 66 invn[i] = 1ll * inv[i] * invn[i - 1] % MO; 67 } 68 69 //printf(" = %lld \n", 142606337ll * fac[8] % MO); 70 71 int T; 72 scanf("%d", &T); 73 while(T--) { 74 solve(); 75 } 76 77 return 0; 78 }
1 #include <bits/stdc++.h> 2 3 #pragma GCC optimize("Ofast") 4 5 typedef long long LL; 6 7 const int MO = 998244353, N = 5000010; 8 9 int n, m, K, L; 10 int fac[N], inv[N], invn[N], val[N], ival[N], D[N]; 11 12 inline int qpow(int a, int b) { 13 int ans = 1; 14 while(b) { 15 if(b & 1) ans = 1ll * ans * a % MO; 16 a = 1ll * a * a % MO; 17 b = b >> 1; 18 } 19 return ans; 20 } 21 inline int Inv(int x) { 22 if(x < N && x >= 0) return inv[x]; 23 return qpow(x, MO - 2); 24 } 25 inline int C(int n, int m) { 26 if(n < 0 || m < 0 || n < m) return 0; 27 return 1ll * fac[n] * invn[m] % MO * invn[n - m] % MO; 28 } 29 inline int Down(int n, int k) { 30 return 1ll * fac[n] * invn[n - k] % MO; 31 } 32 inline int iDown(int n, int k) { 33 return 1ll * invn[n] * fac[n - k] % MO; 34 } 35 inline int dec(int x) { 36 return 1ll * (n - x) * (m - x) % MO * (L - x) % MO; 37 } 38 39 inline void solve() { 40 41 scanf("%d%d%d%d", &n, &m, &L, &K); 42 K--; 43 int ans(0), lm(std::min(std::min(n, m), L)); 44 int V = 1ll * n * m % MO * L % MO; 45 46 val[0] = 1; 47 D[0] = V; 48 for(register int i(1); i <= lm; ++i) { 49 D[i] = (dec(i)); 50 val[i] = 1ll * val[i - 1] * (V - D[i]) % MO; 51 } 52 ival[lm] = qpow(val[lm], MO - 2); 53 for(register int i(lm - 1); i >= K; --i) { 54 ival[i] = 1ll * ival[i + 1] * (V - D[i + 1]) % MO; 55 } 56 int t = 1ll * Down(n - 1, K - 1) * Down(m - 1, K - 1) % MO * Down(L - 1, K - 1) % MO; 57 for(register int i(K); i <= lm; ++i) { 58 //t = 1ll * t * (n - i) % MO * (m - i) % MO * (L - i) % MO * inv[i - K] % MO; 59 t = 1ll * t * D[i] % MO * inv[i - K] % MO; 60 int p = 1ll * t * ival[i] % MO * fac[i] % MO; 61 ((K + i) & 1) ? ans -= p : ans += p; 62 if(ans >= MO) ans -= MO; 63 if(ans < 0) ans += MO; 64 } 65 ans = 1ll * ans * invn[K] % MO; 66 printf("%d\n", ans < 0 ? ans + MO : ans); 67 return; 68 } 69 70 /* 71 1 72 1000 1000 1000 10 73 */ 74 75 int main() { 76 77 fac[0] = inv[0] = invn[0] = 1; 78 fac[1] = inv[1] = invn[1] = 1; 79 for(register int i(2); i < N; ++i) { 80 fac[i] = 1ll * i * fac[i - 1] % MO; 81 inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO; 82 invn[i] = 1ll * inv[i] * invn[i - 1] % MO; 83 } 84 85 //printf(" = %lld \n", 142606337ll * fac[8] % MO); 86 87 int T; 88 scanf("%d", &T); 89 while(T--) { 90 solve(); 91 } 92 93 return 0; 94 }
这题非常卡常...