Codeforces Round #690 (Div. 3) E2 Close Tuples (hard version)

Meaning of the question :
n numbers are given, the range is 1~n, the numbers may be repeated.
Now give you a k and m, ask you how many options you can choose, choose m elements with different subscripts, and let the difference between the maximum value and the minimum value be less than or equal to k

The difference between E1 and E2 is that E1 k=2, m=3 and does not require modulo

Ideas :
① Consider, we only need to enumerate the maximum value, and then calculate the first minimum value that is satisfied, see how many numbers there are in this interval, and then select m. So we sort the sequence from small to large, traversing from the mth number to the nth number, all as the maximum value of the sequence.

② We can calculate the first position pos greater than or equal to a[i]-k by dichotomy, and then we can calculate from pos to the current position i, the interval length num is i-pos+1

③ We have to choose m numbers. Please pay attention here. We must choose the current position, so the number of plans is C(num-1, m-1) . The answer is the accumulation of all the schemes.

④ For E2, we can deal with factorial in advance and then the complexity of each calculation is log.
For E1, there is no need to take the modulus, and because m=2, the calculation is
C(num-1, 2) =num-1) × (num-2) / 2

The E1 code will not be posted.
The E2 code is as follows

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+50;
const ll mod=1e9+7;
ll a[N],f[N];
ll qpow(ll a,ll b){
    
    
    ll ans=1;
    a%=mod;
    while(b){
    
    
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
ll C(int n,int m){
    
    
    if(n<m) return 0;
    return f[n]*qpow(f[m]*f[n-m],mod-2);
}
int main(){
    
    
    f[0]=1;
    for(int i=1;i<N;i++) f[i]=f[i-1]*i%mod;
    int T;cin>>T;
    while(T--){
    
    
        int n,m,k;cin>>n>>m>>k;
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+n+1);
        ll ans=0;
        for(int i=m;i<=n;i++){
    
    
            int pos=lower_bound(a+1,a+n+1,a[i]-k)-a;
            int num=i-pos+1;
            ans+=C(num-1,m-1);
            ans%=mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_43563669/article/details/111298514