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 }
50分代码,帮助理解

相关文章:

  • 2021-07-18
  • 2021-07-09
  • 2021-10-18
  • 2021-06-07
  • 2021-06-06
  • 2021-07-17
  • 2021-09-18
  • 2021-08-31
猜你喜欢
  • 2021-07-30
  • 2022-02-26
  • 2022-01-13
  • 2022-02-13
  • 2022-12-23
  • 2021-11-25
  • 2022-12-23
相关资源
相似解决方案