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 (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

原文地址:https://www.cnblogs.com/zhanhonhao/p/11308325.html

时间: 2024-10-28 02:33:30

Codeforces C. Maximum Value(枚举二分)的相关文章

Codeforces 484B Maximum Value(高效+二分)

题目链接:Codeforces 484B Maximum Value 题目大意:给定一个序列,找到连个数ai和aj,ai%aj尽量大,并且ai≥aj 解题思路:类似于素数筛选法的方式,每次枚举aj,然后枚举k,每次用二分找到小于k?aj并且最大的ai,维护答案,过程中加了一些剪枝. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn =

Codeforces 496D Tennis Game 枚举+二分

题目链接:点击打开链接 题意: 给定n场比赛. 下面n个数字:表示该场是1获胜还是2获胜. 1.胜利者获得一分. 2.若已经决出整个赛季的胜负则比赛不会继续. 3.设要赢得这个赛季需要赢有s局,每局先获得t分的选手胜利. 问: 找出所有的(s,t)组合使得给定的n场比赛记录合法. 输出要排序. 枚举t. a数组存第一个人赢的哪些场次. b数组存第二个人赢的哪些场次. 设赢t分为一句.则判断 第一个人再赢t分是第几场,第二个人再赢t分是第几场. 显然先赢得t分的人赢了这场. 这样同时跑2个人的场数

HDU 1839 Delay Constrained Maximum Capacity Path(二分+最短路)

题目地址:HDU 1839 我去..原来这题这么简单...网络流中这种二分建图的方式做了一大堆了..这种题还能难倒我吗...白天一直没怎么看懂题,对题意懵懵懂懂的...晚上好好看了看题,这不就是网络流中练的最多的那种二分建图模型吗....只是把网络流算法改成最短路就行了..但是两个地方手残了没能在实验室当场A掉..sad... 这题就是二分最小容量,对满足容量的加边,对时间求最短路.如果最短时间比规定时间少的话就可以继续增加容量,直到不能增加为止. 代码如下: #include <iostrea

hdu4430之枚举+二分

Yukari's Birthday Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2549    Accepted Submission(s): 522 Problem Description Today is Yukari's n-th birthday. Ran and Chen hold a celebration party

CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。

1514: Packs Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 61  Solved: 4[Submit][Status][Web Board] Description Give you n packs, each of it has a value v and a weight w. Now you should find some packs, and the total of these value is max, total of

hdu 4430 Yukari&#39;s Birthday 枚举+二分

注意会超long long 开i次根号方法,te=(ll)pow(n,1.0/i); Yukari's Birthday Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3262    Accepted Submission(s): 695 Problem Description Today is Yukari's n-th birt

Eqs 折半枚举+二分查找 大水题

Eqs 题目抽象:a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 (*),给出a1,a2,a3,a4,a5.    ai属于[-50,50]. 求有多少序列   x1,x2,x3,x4,x5 ,xi属于 [-50,50]-{0}. 思路:折半枚举+二分查找 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #inclu

UVA10277 - Boastin&#39; Red Socks(枚举+二分)

UVA10277 - Boastin' Red Socks(枚举+二分) 题目链接 题目大意:现在有m只红袜子,n只黑袜子,这样总袜子total = n + m;现在给你p, q,确定n和m,使得从这些袜子中取两只都是红袜子的概率等于p/q:如果没有这样的n和m满足要求输出impossible; 解题思路:m *(m - 1) / (total * (total - 1)) = p /q; 那么我们只需要枚举total,就可以解到m.但是会有精度误差,貌似有解决的办法,但是觉得没法理解.后面看了

Codeforces 374D Inna and Sequence 二分+树状数组

题目链接:点击打开链接 给定n个操作,m长的序列a 下面n个数 if(co>=0)则向字符串添加一个co (开始是空字符串) else 删除字符串中有a的下标的字符 直接在序列上搞,简单模拟 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h&