Integral Array(因数/思维/前缀和/排序)

该博客主要讨论了一个数组问题,即判断一个整数数组是否为Integral数组。 Integral数组的定义是,对于数组中任意两个元素x和y,如果x大于等于y,则x除以y的下取整值必须也在数组内。博主通过反证法和前缀和技巧给出了解决方案,遍历数组并检查每个元素,寻找不符合条件的元素来否定 Integral 数组的性质。代码使用C++编写,并进行了性能优化以避免重复检查和提高效率。
摘要由CSDN通过智能技术生成

题目
题意:给定一个长度为 n n n的数组 a a a,其中 a i < = c , 1 < = n , c < = 1 0 6 a_i<=c,1<=n,c<=10^6 ai<=c,1<=n,c<=106。判断 a a a是否为Integral数组,数组为Integral数组,当前仅当,任意元素 x , y ∈ a , x > = y x,y \in a,x>=y x,ya,x>=y,有 ⌊ x / y ⌋ ∈ a \lfloor x/y \rfloor \in a x/ya

思路:留意到 a i ∈ 1 0 6 a_i \in 10^6 ai106,我们取反证法。对于数组中的任意元素 y y y,如果存在 r ∉ a r \notin a r/a,而存在元素 x ∈ a , ⌊ x / y ⌋ = = r x \in a,\lfloor x/y \rfloor == r xa,x/y==r,则说明数组 a a a不是Integral数组。
我们遍历数组的每个元素 y y y,遍历所有的不属于 a a a的元素 r r r,观察 [ y ∗ r , y ∗ ( r + 1 ) − 1 ] [y*r,y*(r+1)-1] [yr,y(r+1)1]是否存在元素(前缀和)属于 a a a y ∗ r < = 1 0 6 y*r<=10^6 yr<=106

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1000010;

int n, c;
int a[maxn];
int mp[maxn], sum[maxn];
void solve()  {
	scanf("%d%d", &n, &c);
	for (int i = 1; i <= c; ++i) {
		mp[i] = 0;
		sum[i] = 0;
	}
	for (int i = 0; i < n; ++i) {
		scanf("%d", &a[i]);
		mp[a[i]] = 1;
	}
	sum[0] = 0;
	for (int i = 1; i <= c; ++i) {
		sum[i] = sum[i-1] + mp[i];
	}
	bool flag = 1;
	sort(a, a + n);
	for (int i = 0; i < n && flag; ++i) {
		if (i && a[i] == a[i-1]) {// 去重 ,防TLE
			continue;
		}
		int &y = a[i];
		for (int r = 1; r <= c && flag; ++r) {
			if (1LL * y * r > c) break;
			if (mp[r]) continue;
			// 检查是否存在x属于a,使得 x/y == r,而r不属于a 
			int dl = y * r, dr = min(1LL * y * (r + 1) - 1, 1LL * c);
			if (sum[dr] - sum[dl-1]) {
				flag = 0;
			}
		}
	}
	printf("%s\n", flag ? "Yes" : "No");
	
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值