F. Ira and Flamenco

题目链接:Problem - F - Codeforces

题目大意:给n,m n个数让从中选m个数满足一下条件:

1.m个数互不相同

2.里面的任意两个数相减的绝对值不能超过m

求这n个数有多少组数据满足。

第一行包含一个整数 t ( 1 ≤ t ≤ 1e4 ) - 测试用例数。

每个测试用例的第一行包含整数 n 和 m ( 1≤ m ≤ n ≤ 2⋅1e5 ) 

每个测试用例的第二行包含 n 个整数 a1,a2,…,an ( 1≤ ai ≤ 1e9 ) 。

保证所有测试用例的 n 之和不超过 2⋅1e5。

用到的知识:滑动窗口, 乘法原理,  乘法逆元

解题思路:首先通过选择m个数, 要不同,两两组合不能相减绝对值不可以超过m, 即里面的最大值与最小值之差不可以超过m, 所以可以采用滑动窗口实现, 窗口大小m.

组合数学的运用, 当有重复的数出现, 那么就会用到乘法原理, 列如 m==2,对于数列 1 2 2 3 4 对于 数列1 2 时, 2可以有两种选择, 所以再该窗口时, 应要乘以二。 

 而对于当窗口滑动时,滑出窗口的数的个数要被除下来, 由于题目要求ans要取模1e9+7, 所以用到乘法逆元,即可以实现整个窗口的滑动。MOD = 1e9+7, 可以使用费马小定理求出逆元。

为了选择去重与排序,采用map收集。

#include
using namespace std;

using i64 = long long;
using i128 = __int128;

const int MOD = 1e9+7;
i64 ksm(i64 a, i64 b){
    i64 res = 1;
    while(b) {
        if(b&1) {
            res = res * a % MOD;
        }
        b>>=1;
        a  = a * a % MOD;
    }
    return res;
}
void solve(){
    int n, m;
    cin >> n >> m;
    vector a(1);
    i64 ans = 0;
    map mp;
    for(int i=0; i> t;
        mp[t] ++;
    }
    for(auto& [x,y] : mp) {
        a.push_back(x);//去重
    }
    sort(a.begin(), a.end());
    int i=1, j=1;
    int sz = a.size();
    i64 cnt = 1;
    while(i> t;
    while(t--) {
        solve();
    }
}

  感谢各位的收看与点赞, 欢迎大佬指正。 

你可能感兴趣的:(算法,滑动窗口,乘法原理,乘法逆元)