分析:一个暴力的思想是枚举g,然后枚举每个数ai,看能不能符合要求,这样复杂度是O(nA)的,直接T掉了.也没什么其他的办法了,在暴力的基础上优化一下,优化的关键是要如何快速统计出不满足要求的数的个数.利用数据结构?想不到.仔细分析一下,不满足要求的数组成了很多区间,每次i枚举g的倍数,不满足要求的数的区间总在[i + k + 1,i + g - 1]中,因为i+k+1通过减k满足不了要求,i+g-1比g的倍数少了1,那么利用前缀和数组维护一下个数就好了.不过有一种特殊情况:k >= g - 1,这样无论如何都是满足要求的,因此在前缀和的时候要判断一下左右端点是否合理.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int maxn = 3000010; int sum[maxn], num[maxn],t,n,k,f,mx; int main() { scanf("%d", &t); while (t--) { memset(sum, 0, sizeof(sum)); memset(num, 0, sizeof(num)); scanf("%d%d%d", &n, &k, &f); for (int i = 1; i <= n; i++) { int t; scanf("%d", &t); num[t]++; mx = max(mx, t); } for (int i = 1; i <= mx; i++) sum[i] = sum[i - 1] + num[i]; for (int g = 1; g <= mx; g++) { int cnt = sum[g - 1]; for (int i = g; i + k + 1 <= mx && cnt <= f; i += g) { int l = i + k + 1, r = min(mx, i + g - 1); if (l <= r) cnt += sum[r] - sum[l - 1]; } if (cnt <= f) printf("%d ", g); } printf("\n"); } return 0; }
时间: 2024-11-05 21:25:50