题意:给你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
*/
#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
*/
看见数据范围知道要