题目大意
对于给定序列
a
1
,
a
2
,
.
.
.
,
a
n
a_{1},a_{2},...,a_{n}
a1,a2,...,an
求有多少对
i
1
<
i
2
<
.
.
.
<
i
m
i_{1}<i_{2}<...<i_{m}
i1<i2<...<im满足条件:
m
a
x
(
a
i
1
,
a
i
2
,
.
.
.
,
a
i
m
)
−
m
i
n
(
a
i
1
,
a
i
2
,
.
.
.
,
a
i
m
)
≤
k
max(a_{i1},a_{i2},...,a_{im})-min(a_{i1},a_{i2},...,a_{im}) \le k
max(ai1,ai2,...,aim)−min(ai1,ai2,...,aim)≤k
样例输入
4
3
1 4
2 3
3 6
4
1 2
2 3
3 5
4 5
5
1 2
3 8
4 5
6 7
9 10
5
1 5
2 4
3 5
3 8
4 8
样例输出
0
1
2
0
解题思路
显然是一个组合计数问题,由于
1
≤
a
i
≤
n
1\leq a_{i} \leq n
1≤ai≤n。
因此计数
a
i
a_{i}
ai ,累加组合数
C
s
u
m
[
c
n
t
[
l
]
,
.
.
.
,
c
n
t
[
l
+
k
]
]
m
C_{sum[cnt[l],...,cnt[l+k]]} ^{m}
Csum[cnt[l],...,cnt[l+k]]m。
要注意一下当前组合数中可能包含之前的贡献,减去这部分即可。
(一开始
m
e
m
s
e
t
memset
memset初始化整个
c
n
t
cnt
cnt数组一直
t
l
e
tle
tle,发现
t
t
t可以到
2
e
5
2e5
2e5,只初始化
c
n
t
[
1...
n
]
cnt[1...n]
cnt[1...n]即可,改下这就
A
C
AC
AC了)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ls rt<<1
#define rs rt<<1|1
const int N=2e5+6;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-9;
const double pi=acos(-1);
int cnt[N],pre[N];
ll C[N][105];
void prework(){
C[0][0]=1;
for(int i=1;i<=200005;++i){
C[i][0]=1;
for(int j=1;j<=100;++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
int main(){
prework();
int t;scanf("%d",&t);
while(t--){
int n,m,k;scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i) cnt[i]=0;
for(int i=1;i<=n;++i){
int a;scanf("%d",&a);
cnt[a]++;
}
for(int i=1;i<=n;++i) pre[i]=pre[i-1]+cnt[i];
ll ans=0;
int pr=0;
for(int l=1;l<=n&&pr<n;++l){
int r=min(l+k,n);
if(cnt[l]==0) continue;
int t1=pre[r]-pre[l-1];
int t2=0;
if(pr>=l) t2=pre[pr]-pre[l-1];
ans=(ans+C[t1][m])%mod;
if(pr>=l) ans=(ans-C[t2][m]+mod)%mod; //减去重复累加的贡献
pr=r;
}
printf("%lld\n",ans);
}
return 0;
}