CF1648B Integral Array 解题报告
CF1648B Integral Array
给定一个数组
a , 我们称该数组完整需要满足 :若数组a 中存在两数x,y , 使y \le x (x,y 可以是同一个数) , 则\left\lfloor\dfrac{x}{y}\right\rfloor 也必须在数组\ a 中 , 现需要判断数组\ a 是否完整 。
T \le 10^4 ,\sum n\le 10^6,\sum c\le 10^6 , 其中\ T 为数据组数 ,\ n 为\ a 的元素个数,满足a 中元素\le c 。
分析
直接枚举
所以我们考虑如何优化这个枚举。
引理1
\forall n \in \mathbb{N}_{+}, \left|\left\{ \lfloor \frac{n}{d} \rfloor \mid d \in \mathbb{N}_{+},d\leq n \right\}\right| \leq \lfloor 2\sqrt{n} \rfloor 简略证明:
对于
d\leq \left\lfloor\sqrt{n}\right\rfloor 来说,\left\lfloor\frac{n}{d}\right\rfloor 有\left\lfloor\sqrt{n}\right\rfloor 种取值对于
d> \left\lfloor\sqrt{n}\right\rfloor 来说,有\left\lfloor\frac{n}{d}\right\rfloor\leq\left\lfloor\sqrt{n}\right\rfloor 同样只有\left\lfloor\sqrt{n}\right\rfloor 种取值(from OI-wiki)
根据引理 1,我们知道了实际上不同的
判断的部分,我们可以开一个桶来储存每一个数字的出现个数,对这个桶做前缀和就可以很方便的在
但是这样的时间复杂度是
我们换一种思路考虑,采用一个类似线性筛的思路。同样是枚举
根据调和级数相关有
代码
const int N = 2e6 +10000;
int n,c,a[N],buc[N],pre[N];
void solve() {
read(n,c);
for (int i = 1;i <= 2*c;++i) pre[i] = 0,buc[i] = 0;//注意初始化到 2 * c
for (int i = 1;i <= n;++i) read(a[i]),buc[a[i]]++;
for (int i = 1;i <= 2*c;++i) pre[i] = pre[i - 1] + buc[i];
bool flag = 0;
for (int i = 1;i <= c;++i) {
if (!buc[i]) continue;
for (int j = 1;i * j <= c;++j) {
int l = i * j,r = i * (j + 1) - 1;
if (!buc[j]) {
if (pre[r] - pre[l - 1]) {
flag = 1;
break;
}
}
}
}
if (!flag) puts("Yes");
else puts("No");
}
signed main() {
int T;read(T);
while (T--) solve();
return 0;
}
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭