題意node
給一個長度爲\(n\)的數組,取\(m\)個數字,其中最大值最小值相差不大於\(k\),問這種方式有多少種,答案\(\mod 10^9+7\)。ios
分析c++
經過簡單版本大概瞭解了這題要枚舉最小值來判斷個數,那麼咱們枚舉最小值\(i\),其餘的數都要在\([i,i+k]\)中取,而不能所有都在\([i+1,i+k]\)中取,不然與枚舉的最小值\(i\)不符。數組
採用容斥原理,將在\([i,i+k]\)取數的狀況減去在\([i+1,i+k]\)取數的狀況便可。spa
組合數能夠預處理,也能夠採用預處理階乘處理,也能夠使用盧卡斯定理。(預處理時記得控制空間)code
#pragma GCC optimize(3, "Ofast", "inline") #include <bits/stdc++.h> #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define ll long long #define ull unsigned long long #define int ll #define ls st<<1 #define rs st<<1|1 #define pii pair<int,int> #define rep(z, x, y) for(int z=x;z<=y;++z) #define repd(z, x, y) for(int z=x;z>=y;--z) #define com bool operator<(const node &b)const using namespace std; mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count()); const int maxn = (ll) 4e5 + 5; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; int T = 1; int num[maxn]; int sum[maxn]; int c[(ll) 2e5 + 5][105]; void solve() { int n, m, k; cin >> n >> m >> k; rep(i, 1, 2 * n)num[i] = sum[i] = 0; rep(i, 1, n) { int x; cin >> x; ++num[x]; } rep(i, 1, 2 * n)sum[i] = sum[i - 1] + num[i]; int ans = 0; rep(i, 1, n) { ans = (((ans + c[sum[i + k] - sum[i - 1]][m]) % mod - c[sum[i + k] - sum[i]][m]) % mod + mod) % mod; } cout << ans << '\n'; } signed main() { start; c[0][0] = 1; c[1][0] = c[1][1] = 1; rep(i, 2, 2e5) { c[i][0] = 1; rep(j, 1, 100) { c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod; } } cin >> T; while (T--) solve(); return 0; }