• 【题解】已经没有什么好害怕的了


      套路满满的样子(o°ω°o) 实际上在发现‘比...多 (K) 实际上就是要求糖果能量大于药片能量的组数为 (K') 时,这题的指向性就很明确了。按照惯例来说,我们应当试图用‘至少’来求出‘恰好’的方案数。

      先考虑容斥的部分:如果可以求出每一个糖果集合 (T) 使得 (T) 中的所有糖果在最后的组合方案中能量都能够大于所匹配的药片的能量的方案数 (h_{i}),那么令

    (ans = sum_{Tsubseteq S}^{ }f_{t}*h_{t})

    由于只要恰好为 (K) 的方案数

    所以一个‘糖果大于药片’组数为 (T) 的方案应对答案产生贡献为:

    (g_{x}=sum_{i = 0}^{x}f_{i}*inom{x}{i}=[x = K])

    二项式反演,即可得:

    (f_{x}=sum_{i = 0}^{x}(-1)^{x - K}*inom{x}{K})

      解决了容斥系数,再考虑如何求出至少 (i) 组中糖果能量大于药片能量的方案数?由于题目允许 (n^{2}) 的复杂度,不妨大胆设dp状态 (dp[i][j]) 表示将糖果与药片均从小到大排序后,糖果组合到第 (i) 个,已经有 (j) 组糖果 > 药片的方案数。考虑当前糖果是组合一个比自己大的还是暂不考虑即可。最后求得的方案数中,虽然保证了有 (x) 组糖果 > 药片,但并没有对剩下的元素提出要求。所以都乘上一个 (fac[n - x]) 即为所求。

      完美解决ヾ(o´∀`o)ノ

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 3005
    #define CNST 3000
    #define mod 1000000009
    int n, K, ans, C[maxn][maxn], f[maxn][maxn];
    int fac[maxn], g[maxn], rec[maxn], a[maxn], b[maxn];
    
    int read()
    {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    void Up(int &x, int y) { x = (x + y) % mod; }
    void Pre()
    {
        fac[0] = 1; for(int i = 1; i < maxn; i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
        for(int i = 0; i < CNST; i ++) C[i][0] = 1;
        for(int i = 1; i < CNST; i ++)
            for(int j = 1; j < CNST; j ++)
                C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; 
    }
    
    void DP()
    {
        f[0][0] = 1;
        for(int i = 0; i <= n; i ++)
            for(int j = 0; j <= i; j ++)
            {
                int t = i + 1;
                Up(f[t][j], f[i][j]);
                if(rec[t] > j) Up(f[t][j + 1], 1ll * f[i][j] * (rec[t] - j) % mod);
            }
        for(int i = 1; i <= n; i ++) f[n][i] = 1ll * f[n][i] * fac[n - i] % mod;
    }
    
    void In_ex()
    {
        for(int i = K; i <= n; i ++)
            g[i] = 1ll * (((i - K) & 1) ? -1 : 1) * C[i][K] % mod;
        for(int i = K; i <= n; i ++) 
            Up(ans, 1ll * g[i] * f[n][i] % mod);
    }
    
    int main()
    {
        n = read(), K = read(); Pre(); 
        if(n + K & 1) { printf("0
    "); }
        else K = (n + K) >> 1;
        for(int i = 1; i <= n; i ++) a[i] = read();
        for(int i = 1; i <= n; i ++) b[i] = read();
        sort(a + 1, a + 1 + n);
        sort(b + 1, b + 1 + n);
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                if(b[j] > a[i]) { rec[i] = j - 1; break; }
                else if(j == n) rec[i] = n;
        DP(); In_ex();
        printf("%d
    ", (ans + mod) % mod);
        return 0;
    }
  • 相关阅读:
    再谈数据湖3.0:降本增效背后的创新原动力
    基于开源PolarDBX打造中正智能身份认证业务数据基座
    开源数据库PolarDB为什么能捕获娃哈哈的心?
    PolarDB开源未来将有哪些新动向?阿里云数据库开源负责人来解答
    谈谈PolarDBX在读写分离场景的实践
    科普达人丨一图看懂块存储&云盘
    科普达人丨一图看懂阿里云ECS
    网络编程框架Netty
    结构型模式
    网络编程框架Netty1
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/10162743.html
Copyright © 2020-2023  润新知