Codeforces C. Maximum Value(枚举二分)

题目描述:

Maximum Value

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a sequence a consisting of n integers. Find the maximum possible value of img (integer remainder of *a**i* divided by *a**j), where 1 ≤ i, j ≤ n* and ai ≥ aj.

Input

The first line contains integer n — the length of the sequence (1 ≤ n ≤ 2·105).

The second line contains n space-separated integers *a**i* (1 ≤ *a**i* ≤ 106).

Output

Print the answer to the problem.

Examples

Input

Copy

33 4 5

Output

Copy

2

思路:

题目是说,给一个数列,求这个数列的任两个数中大数模小数的最大值。先说说正确的思路,考虑每个数,枚举它的倍数,在数列中每次二分查找比这个倍数大于等于的数的位置,减一后就是这个数被数列中的数模得到最大值的位置。具体的,a[i]来说,我们每次枚举a[i]的倍数,发现\([a[i]*k,a[i]*(k+1))\),在这个区间内一个数模a[i]值是递增的。那么数列中最接近\(a[i]*(k+1)\)的数来%a[i]就可以得到最大值。这个数怎么求呢?具体的,就是lower_bound找到大于等于\([i]*(k+1)\)的值的位置减一。为什么减一,加入数列中刚好有\(a[i]*(k-1)\),我们减一就得到最接近它的数,如果没有,减一也得到了最接近它的数。注意题目要求要大数模小数。

再来说说一个看着正确的思路。转化研究对象我们来看对数列中的每一个数,怎么才能让它的余数最大。

比如:9,9%2=1,%3=0,%4=1,%5=4,%6=3,%7=2,%8=1我们发现,当它模自己一半左右的数时取得模的最大值。这个思路就是在数组中二分查找一个数一半的值,在一半的值的位置附近遍历找最大。这个只能过12个测试点,好像。原因呢,可不可以构造出一组数据,让一个数的一半左右的值都不在遍历范围,然后取到不是最大值的数刚刚好在遍历范围内呢?暂时不知道,留待解答。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#define max_n 200005
using namespace std;
int n;
int a[max_n];
int tot = 0;
int cnt[1000005];
int maxm = 0;
inline void read(int& x)
{
    x=0;int f=0;char ch = getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=1;ch=getchar();}
    while('0'<=ch&&ch<='9') {x=10*x+ch-'0';ch=getchar();}
    x=f?-x:x;
}
#pragma optimize(2)
int main()
{
    read(n);
    for(int i = 0;i<n;i++)
    {
        int num;
        read(num);
        if(cnt[num]==0)
        {
            a[tot++] = num;
            cnt[num] = 1;
        }
    }
    sort(a,a+tot);
    for(int i = 0;i<tot;i++)
    {
        for(int j = a[i];j<=2*a[tot-1];j+=a[i])
        {
            int pos = lower_bound(a,a+tot,j+a[i])-a-1;
            if(pos==-1)pos++;
            //cout << "pos " << pos << endl;
            //cout << a[pos] << "%" << a[i] << endl;
            maxm = max(maxm,a[pos]%a[i]);
        }
    }
    cout << maxm << endl;
    return 0;
}

参考文章:

张松超,codeforces 485D. Maximum Value(二分+思维),https://blog.csdn.net/ZscDst/article/details/78775965

猜你喜欢

转载自www.cnblogs.com/zhanhonhao/p/11308325.html