Codeforces Round #690 (Div. 3)E2(组合数)

117 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。
E2. Close Tuples (hard version)
题目

屏幕截图 2022-10-04 171229.png 题意

构造成一个长度为m的序列让其中的最大值与最小值的差值小于等于k

解法

  1. 对于这种题目我们是肯定是需要用到组合数的所以先放上组合数的模板
int Finv[N],fac[N],inv[N];
void init()//n<N
{
    inv[1]=1;
    for(int i=2;i<=N;++i)inv[i]=((MOD-MOD/i)*inv[MOD%i])%MOD;
    fac[0]=Finv[0]=1;
    for(int i=1;i<=N;++i)fac[i]=fac[i-1]*i%MOD,Finv[i]=Finv[i-1]*inv[i]%MOD;
}
int C(int n,int m)
{
    if(m<0||m>n)return 0;
    return fac[n]*Finv[n-m]%MOD*Finv[m]%MOD;
}

2.对数组进行排序这样我们只需要考虑左右两端是否满足
3. 对一个固定的左端点我们只需要去枚举它最大符合的左端点然后求在这个范围内取m-1个数字的种数即可
Code

void solve()
{
   int n,m,k; cin >> n >> m >> k;
   rep(i,n) cin >> a[i];
   sort(a + 1,a + 1 + n);
   int res = 0;
   int r = 1;
   a[n + 1] = 1e18;
   for(int l = 1; l <= n; l++) {
       while(a[r] - a[l] <= k ) r ++;
       res = (res + C(r-l-1,m-1)) % MOD;
   }
   cout << res << endl;
}