• [CF1462E2] Close Tuples (hard version)


    Description

    给出一个由 (n) 个数字组成的数组。现在定义一种子集为 ({A_1, A_2, A_3, ..., A_m}) 使得这个子集中的最大值和最小值的差值不超过 (k),其中 (m)(k) 是给出的。现在问你这种子集有几个。

    Solution

    最初的想法是将每个数的重数统计出来,然后枚举最大的数以及最大数选多少个,剩下的用组合数计算。

    更简单的方法是,直接排序,然后枚举最大数的位置,利用前缀和统计这个数前面有多少个不小于它 (-k) 的数,然后用组合数计算即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int mod = 1e9 + 7;
    const int N = 1e6 + 5;
    
    int fac[N], ifac[N];
    
    int qpow(int p, int q)
    {
        return (q & 1 ? p : 1) * (q ? qpow(p * p % mod, q / 2) : 1) % mod;
    }
    
    int inv(int p)
    {
        return qpow(p, mod - 2);
    }
    
    void presolve()
    {
        fac[0] = 1;
        for (int i = 1; i < N; i++)
            fac[i] = fac[i - 1] * i % mod;
        ifac[N - 1] = inv(fac[N - 1]);
        for (int i = N - 2; i >= 0; i--)
            ifac[i] = ifac[i + 1] * (i + 1) % mod;
    }
    
    int ncr(int n, int m)
    {
        if (n < m)
            return 0;
        return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        int t;
        cin >> t;
    
        presolve();
    
        while (t--)
        {
            int n, m, k;
            cin >> n >> m >> k;
    
            vector<int> a(n + 2);
            vector<int> c(n + n + 2);
    
            for (int i = 1; i <= n; i++)
                cin >> a[i], c[a[i]]++;
    
            for (int i = 1; i <= n; i++)
                c[i] += c[i - 1];
    
            sort(&a[1], &a[n + 1]);
    
            int ans = 0;
    
            for (int i = 1; i <= n; i++)
            {
                int cnt = i -1;
                if (a[i] - k - 1 > 0)
                    cnt -= c[a[i] - k - 1];
                ans += ncr(cnt, m - 1);
                ans %= mod;
            }
    
            cout << ans << endl;
        }
    }
    
  • 相关阅读:
    linux网络编程之socket编程(十四)
    linux网络编程之socket编程(十三)
    linux网络编程之socket编程(十二)
    linux网络编程之socket编程(十一)
    linux网络编程之socket编程(十)
    android:duplicateParentState属性使用场景
    python中操作mysql
    常用python包(依赖)Ubuntu下
    正则匹配汉字文字
    python 使用set对列表去重,并保持列表原来顺序
  • 原文地址:https://www.cnblogs.com/mollnn/p/14320785.html
Copyright © 2020-2023  润新知