codeforces 485D. Maximum Value(二分+思维)

本文介绍了一种通过枚举和二分查找解决求最大余数值问题的方法,利用排序和去重减少计算复杂度,适用于算法竞赛及编程挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你N个元素,求出这N个元素中a[j]%a[i]的最大值, 且 a[j] ≥ a[i](1 ≤ i, j ≤ N)。

思路:枚举a[i],二分查找a[j]。我们可以发现对于a[i]这个值,a[j]%a[i]的值是如图一个以a[i]为周期的变化过程,所以我们找到一个距k*a[i]最近的那个值便是对于a[i]这个值a[j]%a[i]的最大值。我们先排序然后去重(因为重复的数字对答案没有贡献但是会浪费时间),此时我们枚举a[i],再枚举k,二分查找距离k*a[i]最近的那个值就可以了。

这个复杂度大概也是的具体怎么估的,我也不是很会。。。

排序+去重:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
int n, a[MAXN];
int main() 
{
	while(~scanf("%d",&n))
	{
		for(int i = 0; i < n; i++) scanf("%d",&a[i]);
		sort(a, a + n);//排序 
		n = unique(a, a + n) - a;//去重 
		int MAX = 0;
		for(int i = 0; i < n; i++)
		{
			for(int j = a[i]; j <= a[n - 1]; j += a[i])
			{
				int pos = lower_bound(a + i, a + n, a[i] + j) - a - 1;//二分查找 
				MAX = max(MAX, a[pos] % a[i]); 
				if(MAX == a[i] - 1) break;//a[j]%a[i]最大值为a[i] - 1 
			}
		}
		printf("%d\n",MAX);
	}
	return 0;
}
/*
3
3 4 5
2
9 10
3
5 8 10
*/


set:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
int n;
int main() 
{
	while(~scanf("%d",&n))
	{
		set<int> s;//可以排序加去重 
		for(int i = 0; i < n; i++)
		{
			int t; scanf("%d",&t);
			s.insert(t);
		}
		set<int>::iterator BACK=s.end();BACK--; 
		int E = *BACK;//获得最后一个元素的值 
		int MAX = 0;
		for(set<int>::iterator it = s.begin(); it != s.end(); it++)
		{
			for(int j = (*it); j <= E; j += (*it))
			{
				set<int>::iterator itlow = s.lower_bound((*it) + j);itlow--;//二分查找 
				MAX = max(MAX, (*itlow) % (*it));
				if(MAX == (*it) - 1) break;//a[j]%a[i]最大值为a[i] - 1  
			}
		}
		printf("%d\n",MAX);
	}
	return 0;
}
/*
3
3 4 5
2
9 10
3
2 8 10
*/

看见数据范围知道要才能过,也想到了二分,但是如何二分没想到。哎
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值