F. Ira and Flamenco

F. Ira and Flamenco

Ira loves Spanish flamenco dance very much. She decided to start her own dance studio and found $n$ students, $i$th of whom has level $a_i$.

Ira can choose several of her students and set a dance with them. So she can set a huge number of dances, but she is only interested in magnificent dances. The dance is called magnificent if the following is true:

  • exactly $m$ students participate in the dance;
  • levels of all dancers are pairwise distinct;
  • levels of every two dancers have an absolute difference strictly less than $m$.

For example, if $m = 3$ and $a = [4, 2, 2, 3, 6]$, the following dances are magnificent (students participating in the dance are highlighted in red): $[\color{red}{4}, 2, \color{red}{2}, \color{red}{3}, 6]$, $[\color{red}{4}, \color{red}{2}, 2, \color{red}{3}, 6]$. At the same time dances $[\color{red}{4}, 2, 2, \color{red}{3}, 6]$, $[4, \color{red}{2}, \color{red}{2}, \color{red}{3}, 6]$, $[\color{red}{4}, 2, 2, \color{red}{3}, \color{red}{6}]$ are not magnificent.

In the dance $[\color{red}{4}, 2, 2, \color{red}{3}, 6]$ only $2$ students participate, although $m = 3$.

The dance $[4, \color{red}{2}, \color{red}{2}, \color{red}{3}, 6]$ involves students with levels $2$ and $2$, although levels of all dancers must be pairwise distinct.

In the dance $[\color{red}{4}, 2, 2, \color{red}{3}, \color{red}{6}]$ students with levels $3$ and $6$ participate, but $|3 - 6| = 3$, although $m = 3$.

Help Ira count the number of magnificent dances that she can set. Since this number can be very large, count it modulo $10^9 + 7$. Two dances are considered different if the sets of students participating in them are different.

Input

The first line contains a single integer $t$ ($1 \le t \le 10^4$) — number of testcases.

The first line of each testcase contains integers $n$ and $m$ ($1 \le m \le n \le 2 \cdot 10^5$) — the number of Ira students and the number of dancers in the magnificent dance.

The second line of each testcase contains $n$ integers $a_1, a_2, \ldots, a_n$ ($1 \le a_i \le 10^9$) — levels of students.

It is guaranteed that the sum of $n$ over all testcases does not exceed $2 \cdot 10^5$.

Output

For each testcase, print a single integer — the number of magnificent dances. Since this number can be very large, print it modulo $10^9 + 7$.

Example

input

9
7 4
8 10 10 9 6 11 7
5 3
4 2 2 3 6
8 2
1 5 2 2 3 1 3 3
3 3
3 3 3
5 1
3 4 3 10 7
12 3
5 2 1 1 4 3 5 5 5 2 7 5
1 1
1
3 2
1 2 3
2 2
1 2

output

5
2
10
0
5
11
1
2
1

Note

In the first testcase, Ira can set such magnificent dances: $[\color{red}{8}, 10, 10, \color{red}{9}, \color{red}{6}, 11, \color{red}{7}]$, $[\color{red}{8}, \color{red}{10}, 10, \color{red}{9}, 6, 11, \color{red}{7}]$, $[\color{red}{8}, 10, \color{red}{10}, \color{red}{9}, 6, 11, \color{red}{7}]$, $[\color{red}{8}, 10, \color{red}{10}, \color{red}{9}, 6, \color{red}{11}, 7]$, $[\color{red}{8}, \color{red}{10}, 10, \color{red}{9}, 6, \color{red}{11}, 7]$.

The second testcase is explained in the statements.

 

解题思路

  首先可以发现改变数组$a$中元素的位置并不影响答案的统计,因此可以先对数组$a$的元素进行升序排序。由于不能选择重复的元素,因此可以先统计每个元素出现的次数,再对排序好的数组进行进行去重。

  对于排序且去重后的数组$a'$,根据三个约束条件可以知道,我们应该要从$a'$中选择$m$个不同的元素,且任意两个元素的差值严格小于$m$。假设最小的元素为$x$,根据约束条件那么选择的元素一定满足这个形式:$[x, x+1, x+2, \ldots, x+m-1]$。首先这里恰好选择了$m$个不同的元素,且任意两个元素的差值严格小于$m$。因此本质就是在$a'$中选择连续一段的元素,且相邻两个元素的差值恰好为$1$。假设第$i$个元素$a'_{i}$在$a$中出现了$c_i$次,那么根据乘法原理,以$a'_{i}$为最小值且满足约束的一段连续元素的数量就是$\prod\limits_{j=i}^{i+m-1}{c_j} \pmod{{10}^9+7}$。

  因此我们可以枚举所有的元素,将其作为最小值,然后往后找连续$m$个元素看看是否满足约束,如果满足则统计答案。为此可以用双指针,设$i$为满足约束的最右边的元素,$j$为满足约束的最左边的元素,当$i$往右移时$j$也会往右移,同时开个变量维护这一段连续元素(即$j$到$i$)对应的次数的乘积。当$j$往右以很明显需要对这个变量除以$c_j$,但这是个取模的乘法,与之对应的应该是乘以在模${10}^9+7$意义下$c_j$的乘法逆元,而根据费马小定理,对应的逆元就是$c_{j}^{({10}^9+7) - 2} \pmod{{10}^9+7}$。

  AC代码如下,时间复杂度为$O \left( n \log{({10}^9+7)} \right)$:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 typedef pair<int, int> PII;
 6 
 7 const int N = 2e5 + 10, mod = 1e9 + 7;
 8 
 9 int a[N];
10 map<int, int> mp;
11 
12 int qmi(int a, int k) {
13     int ret = 1;
14     while (k) {
15         if (k & 1) ret = 1ll * ret * a % mod;
16         a = 1ll * a * a % mod;
17         k >>= 1;
18     }
19     return ret;
20 }
21 
22 void solve() {
23     int n, m;
24     scanf("%d %d", &n, &m);
25     mp.clear();
26     for (int i = 0; i < n; i++) {
27         scanf("%d", a + i);
28         mp[a[i]]++;    // 统计每个元素出现的次数
29     }
30     sort(a, a + n);
31     n = unique(a, a + n) - a;    // 排序去重
32     int ret = 0, prod = 1;
33     for (int i = 0, j = 0; i < n; i++) {
34         prod = 1ll * prod * mp[a[i]] % mod;
35         while (a[i] - a[j] >= m) {    // 不满足第3个约束,即每个元素的差值应该严格小于m
36             prod = 1ll * prod * qmi(mp[a[j++]], mod - 2) % mod;    // 把c_j除掉,等价于乘以对应的乘法逆元
37         }
38         if (i - j + 1 == m) ret = (ret + prod) % mod;    // 有连续m个不同的元素
39     }
40     printf("%d\n", ret);
41 }
42 
43 int main() {
44     int t;
45     scanf("%d", &t);
46     while (t--) {
47         solve();
48     }
49     
50     return 0;
51 }

  再给出一种用线段树维护区间取模乘法的做法。因为本质就是每次都需要快速知道某段连续区间的取模乘法是多少,因此可以用线段树来进行维护,这样就不需要用到求逆元,一开始没想到这种做法。

  AC代码如下,时间复杂度为$O(n \log{n})$:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10, mod = 1e9 + 7;
 7 
 8 int a[N];
 9 map<int, int> mp;
10 struct Node {
11     int l, r, prod;
12 }tr[N * 4];
13 
14 void build(int u, int l, int r) {
15     if (l == r) {
16         tr[u] = {l, r, mp[a[l]]};
17         
18     }
19     else {
20         int mid = l + r >> 1;
21         build(u << 1, l, mid);
22         build(u << 1 | 1, mid + 1, r);
23         tr[u] = {l, r, 1ll * tr[u << 1].prod * tr[u << 1 | 1].prod % mod};
24     }
25 }
26 
27 int query(int u, int l, int r) {
28     if (tr[u].l >= l && tr[u].r <= r) return tr[u].prod;
29     int mid = tr[u].l + tr[u].r >> 1, ret = 1;
30     if (l <= mid) ret = query(u << 1, l, r);
31     if (r >= mid + 1) ret = 1ll * ret * query(u << 1 | 1, l, r) % mod;
32     return ret;
33 }
34 
35 void solve() {
36     int n, m;
37     scanf("%d %d", &n, &m);
38     mp.clear();
39     for (int i = 1; i <= n; i++) {
40         scanf("%d", a + i);
41         mp[a[i]]++;
42     }
43     sort(a + 1, a + n + 1);
44     n = unique(a + 1, a + n + 1) - a - 1;
45     build(1, 1, n);
46     int ret = 0;
47     for (int i = 1, j = 1; i <= n; i++) {
48         while (a[i] - a[j] >= m) {
49             j++;
50         }
51         if (i - j + 1 == m) ret = (ret + query(1, j, i)) % mod;
52     }
53     printf("%d\n", ret);
54 }
55 
56 int main() {
57     int t;
58     scanf("%d", &t);
59     while (t--) {
60         solve();
61     }
62     
63     return 0;
64 }

 

参考资料

  Codeforces Round #874 (Div. 3) Editorial:https://codeforces.com/blog/entry/116636

posted @ 2023-05-22 09:07  onlyblues  阅读(100)  评论(0编辑  收藏  举报
Web Analytics