【luogu U138097】小鱼吃大鱼(数学)

小鱼吃大鱼

题目链接:luogu U138097

题目大意

给你 n 个数,你可以选两个数,让小的取模大的,问你结果最大可以是多少。

思路

直接暴力搞当然会 T 飞,我们考虑枚举取模的数。

然后再枚举其倍数,然后这样是 n l o g n nlogn nlogn
接着枚举倍数那我们这一段之前我们就要找最接近倍数的数,也就是这一段里面最大的。
然后我们可以用一个前缀和先搞着,然后就二分最大的位置,判断后面那一大段那里面有没有数。

总的复杂度是 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n),还是可以过的。

然后记得判一下边边角角的地方就可以了。

代码

#include<cstdio>
#include<iostream>

using namespace std;

int n, x, bg[2000001];
int answer, re;
int in[1000001];
char c;

int read() {
	re = 0; c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9') {
		re = (re << 3) + (re << 1) + c - '0';
		c = getchar();
	}
	return re;
}

int main() {
//	freopen("sj.txt", "r", stdin);
	
	n = read();
	for (int i = 1; i <= n; i++) {
		x = read();
		in[x] = 1;
	}
	
	for (int i = 1; i <= 1000000; i++) {
		bg[i] = bg[i - 1] + in[i];
	}
	
	for (int i = 2; i <= 1000000; i++)
		if (in[i]) {
			int l = answer, r = i - 1, ans = 0, rr = i - 1;
			if (i + r > 1000000) r = rr = 1000000 - i;
			while (l <= r) {
				int mid = (l + r) >> 1;
				bool yes = 0;
				for (int j = i; j <= 1000000; j += i) {
					if (j + mid - 1 <= 1000000 && bg[min(j + rr, 1000000)] - bg[j + mid - 1]) {
						yes = 1; break;
					}
				}
				if (yes) ans = mid, l = mid + 1;
					else r = mid - 1;
			}
			answer = max(answer, ans);
		}
	
	printf("%d", answer);
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值