HDU 7073 Integers Have Friends 2.0

题目链接

HDU 7073 传送门

题意简述

给出一个整数数集合 { a 1 , a 2 , ⋯   , a n }    ( i ≠ j ⇒ a i ≠ a j ) \{a_1, a_2, \cdots, a_n\}\;(i\neq j \Rightarrow a_i\neq a_j) {a1,a2,,an}(i=jai=aj),从中取出一个子集 S S S,如果对于这个子集,存在 m ≥ 2 m\geq 2 m2 使得子集中的所有的数模 m m m 意义下,同余,则称这个子集为友好子集,试求元素个数最多的友好子集有多少个元素。

输入格式

第一行一个正整数 T    ( T ≤ 30 ) T\;(T \leq 30) T(T30),表示总共有 T T T 组数据。

每组数据的第一行包含一个整数 n    ( n ≤ 2 × 1 0 5 ) n\;(n\leq 2\times 10^5) n(n2×105) 表示该集合的元素个数。

第二行输入 n n n 个整数表示 a 1 , ⋯   , a n    ( a i ≤ 4 × 1 0 12 ) a_1, \cdots, a_n\;(a_i\leq4\times 10^{12}) a1,,an(ai4×1012)

数据保证 ∑ n ≤ 1 0 6 \sum n\leq 10^6 n106

解题思路

首先,当 m = 2 m=2 m=2 时,最大友好子集尺寸一定大于等于 n 2 \frac{n}{2} 2n(抽屉原理)。由此可见,整个问题的答案一定大于等于 n 2 \frac{n}{2} 2n。任取数列中的两个数做差,对这个差值进行质因数分解,不难说明,这个差值有不低于 25 % 25\% 25% 概率含有能够让友好子集取到最大的质因子 m m m。多随机取几对 { a i } \{a_i\} {ai} 中的数做差就能够有很大概率找到答案。

代码

#include <cstdio>
#include <set>
#include <cstdlib>
#include <ctime>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;

const int maxn = 200000 + 6;
long long A[maxn]; int ans = 0;

void test(long long m, long long base, const int n) {
	int cnt = 0;
	for(int i = 1; i <= n; i ++) {
		if(abs(A[i] - base) % m == 0) cnt ++;
	}
	ans = max(ans, cnt);
	if(m == 2) ans = max(ans, n - cnt); /// m = 2 时只能拆分出两个集合 
}

int rand(int L, int R) { /// 生成 [L, R] 区间内的随机数 
	int RND = abs((rand() << 15) | rand());
	return RND % (R - L + 1) + L;
}

void load(long long tmp, long long base, const int n) { /// 装载一个差值 
	if(tmp <= 1) return;
	for(long long i = 2; i <= sqrt(tmp) + 0.5; i ++) {
		if(tmp % i == 0) {
			while(tmp%i == 0) tmp /= i;
			test(i, base, n);
		}
	}
	if(tmp != 1) test(tmp, base, n);
}

int main() {
	srand(time(NULL)); /// 重置随机种子 
	int T; scanf("%d", &T);
	while(T --) {
		int n; scanf("%d", &n);
		ans = 0;
		for(int i = 1; i <= n; i ++) scanf("%lld", &A[i]);
		test(2, 0, n); /// 2 一定是一个很优秀的解法 
		for(int t = 1; t <= 20; t ++) {
			int l = rand(1, n-1), r = rand(l+1, n);
			load(abs(A[l] - A[r]), A[l], n);
		}
		printf("%lld\n", ans);
	}
	return 0; 
}

调参最后发现随机生成 20 20 20 组能过, 40 40 40 组常数太大,我的算法会 TLE

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值