zoukankan      html  css  js  c++  java
  • 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
    ", (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 
    ", 142606337ll * fac[8] % MO);
    70     
    71     int T;
    72     scanf("%d", &T);
    73     while(T--) {
    74         solve();
    75     }
    76     
    77     return 0;
    78 }
    50分代码,帮助理解
     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
    ", 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 
    ", 142606337ll * fac[8] % MO);
    86     
    87     int T;
    88     scanf("%d", &T);
    89     while(T--) {
    90         solve();
    91     }
    92     
    93     return 0;
    94 }
    AC代码

    这题非常卡常...

  • 相关阅读:
    mysql前缀索引的应用
    记博客园
    好的博客网站(随手记)
    memcache应对缓存失效问题
    memcache内存分配问题
    memcached使用libevent 和 多线程模式
    RabbitMQ用户及权限控制
    Nginx基础之常用配置
    PHP-fpm进程池优化方法
    php-fpm参数详解
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10951310.html
Copyright © 2011-2022 走看看