Codeforces Round #845 (Div. 2) C
![](https://i-blog.csdnimg.cn/blog_migrate/806bea25f3b85a6b4ab190bbfb984c44.png)
两个遍历复杂度太高了,我就固定一个如何右边延长至满足题意,然后左边再走,右边继续延长。
add()和del()中求出现一次的思路,和所有因子遍历方法
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
const int mod = 1e9 + 7;
#define ll long long
const int maxn = 1e5 + 5, INF = 1e9;
int cnt[maxn], a[maxn], sum;//sum用来判断 1 - n 中 此时一共有多少个数是满足题意的
int n, m;
void add(int x) {
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
if (i <= m) { //比较小的因子
if (++cnt[i] == 1) sum++;//刚好出现一次我sum++
}
if (x / i <= m && i * i != x) {//相对比较小的因子的比较大的因子
if (++cnt[x / i] == 1) sum++;
}
}
}
}
void del(int x) {
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
if (i <= m) {
if (--cnt[i] == 0) sum--;
}
if (x / i <= m && i * i != x) {
if (--cnt[x / i] == 0) sum--;
}
}
}
}
void solve() {
cin >> n >> m;
for (int i = 1; i <= m; i++) cnt[i] = 0;
sum = 0;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
int ans = INF;
for (int i = 1, j = 0; i <= n; i++) {
del(a[i - 1]);
while (j + 1 <= n && sum < m) add(a[++j]);
if (sum == m) ans = min(ans, a[j] - a[i]);
}
if (ans == INF) cout << -1 << '\n';
else cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll T = 1;
cin >> T;
while (T--) solve();
return 0;
}
123