题目描述

小P同学在养殖一种非常凶狠的鱼,而且与其他鱼类不同,这种鱼越大越温顺,反而小鱼最凶残。当两条鱼相遇时, 小鱼会不断撕咬大鱼,每一口都咬下与它自身等重的肉(小鱼保持体重不变),直到大鱼的体重小于这条小鱼(若 两条鱼体重相同,一条鱼会将另一条撕咬殆尽)。

现在池塘中有n条鱼,小P想知道哪一对鱼相遇后,被咬的鱼剩余体重最大。

输入格式

单组测试数据。
第一行包含一个整数n,表示鱼的数量。(1 ≤ n ≤ 2e6) 第二行有n个用空格分开的整数ai 表示第i条鱼的体重(1 ≤ ai ≤ 1e6)。

输出格式

输出一个整数代表结果。

输入输出样例

输入 #1

3
3 4 5
输出 #1

2
输入 #2

2
2 2
输出 #2

0
输入 #3

5
2 1 4 3 5
输出 #3

2

说明/提示

数据范围

对于35%的数据,1≤n≤10,1 ≤ ai ≤ 100
对于55%的数据,1≤n≤10000
对于100%的数据,1 ≤ n ≤ 2e6,1 ≤ ai ≤ 1e6

样例解释

当三条鱼的体重分别为3 4 5时,不同对鱼相遇的结果分别是{3,4}=1 {3,5}=2 {4,5}=1,所以只有第一条跟第三条鱼相 遇时,最后大鱼的体重最大,结果为2

题意

  给定n个数,求一对数(i, j),使得i>j, 且i%j最大。

题解

  考虑枚举每一个数, 筛出它倍数。

  

  对于这幅图, c%x显然大于a,b的结果,容易想到:对于每一个x的倍数, 我们取小于它的第一个数更新答案

  很容易想到通过线性筛来筛倍数,但仔细想并不可以。比如12, 使用线性筛每个数只会筛一次,而12作为2,3,4,6的倍数意义是不一样的:假设12左边是10, 作为3的倍数时答案为1,4的倍数时则是2.

  于是可以想到通过埃氏筛来做。

  考试的时候由于边界细节只有85pts, 要注意,如果使用桶枚举可能会出现:某个数在i*x 和 (i+1)*x 之间, 而(i+1)*x 超过了枚举边间则会漏掉, 具体处理见代码。

  

优化

  如果不是数据太水, 5e5的数据可以把 O(nlog^2n)的埃氏筛瞬间卡炸。

  仔细分析后,大多数算法会被卡的情况是不一样的

    数据过大:埃氏筛常数小, 复杂度稳定,但在数据过大的情况下,多一个log的致命伤就体现出来了。

    数据密集:二分虽然理论上还多一个log,但是在大多数情况下完虐桶+埃氏筛。但是如果没有去重,数据密集就会被卡飞。

    数据松散:刚好相反,没有一个重复的数字会让不加优化的桶卡飞(我就是

  优化方式: 把上面几种加起来就好了


  
综合了几位大佬的写法和自己的代码,得到了一种效果显著的优化。

  1. 用桶储存,这样可以降低一个二分的log, 省掉一个排序,随便还能去重。
  2. 预处理一个last数组,储存每个数的上一个数是什么,例如

  

  last[c] = b, last[b] = c , 同样的last[3x] = c;

  这样我们在查找3x左边的第一个数时, 直接找last[3x]即可。预处理方法见代码。

  3. 反向枚举,判断一下现在枚举的这个数是否大于当前答案, 如果这个数都比答案小, 取模结果肯定更小。对答案没有贡献,直接通过。

  4. 将i--改为i = last[i]  , 朴素的桶在枚举时通过i--, 然后判断这个数是否存在。然而我们既然已经有last数组了,不如好好利用。直接跳到上一个存在的数显然更优。

  

  通过这些优化以及部分细节,可以显著提升效率。 实现其实也很简单

  

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 1000006
#define rr register
int n, ans=0, las[N];
bool a[N]; //快读
int read(){
int num=0; char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0' && c<='9') num = num*10+c-'0', c=getchar();
return num;
} int main(){
n=read();
int maxi=0;
for(rr int i=0; i<n; i++){
int l = read();
a[l] = 1;
if(a[l]) maxi = max(maxi, l);
} rr int ls=-1;
//预处理last数组
for(rr int i=0; i<N; i++){
las[i] = ls;
if(a[i]) ls=i;
}
//i = last[i] 优化近100ms
for(rr int i=las[N-1]; i>=1; i=las[i]){
//判断是否对答案无贡献,优化100ms
if(ans >= i) continue;
//枚举倍数
for(rr int j=2; i*j<N; j++){
if(las[j*i]<=(j-1)*i) continue;
ans = max(ans, las[j*i]-(j-1)*i);
}
//处理边界问题 , 优化近200ms, 没有这一句N需要开到2倍才能AC,
ans = max(ans, maxi%i);
}
printf("%d", ans); return 0;
}

  

  

U138097 小鱼吃大鱼 埃氏筛的更多相关文章

  1. CodeForces - 385C Bear and Prime Numbers (埃氏筛的美妙用法)

    Recently, the bear started studying data structures and faced the following problem. You are given a ...

  2. cf1154G 埃氏筛应用

    直接用埃氏筛也可以做,但是这题写起来有点恶臭.. 更加简单的写法是直接枚举gcd=k,然后里面再枚举一次i*k,即找到k两个最小的倍数,看起来复杂度很高,但其实也是埃氏筛的复杂度 因为每次枚举gcd, ...

  3. 「CF779B」「LOJ#10201.」「一本通 6.2 练习 4」Sherlock and His Girlfriend(埃氏筛

    题目描述 原题来自:Codeforces Round #400 B. Sherlock 有了一个新女友(这太不像他了!).情人节到了,他想送给女友一些珠宝当做礼物. 他买了 nnn 件珠宝.第 iii ...

  4. [JXOI 2018] 游戏 解题报告 (组合数+埃氏筛)

    interlinkage: https://www.luogu.org/problemnew/show/P4562 description: solution: 注意到$l=1$的时候,$t(p)$就 ...

  5. 埃氏筛优化(速度堪比欧拉筛) + 洛谷 P3383 线性筛素数 题解

    我们一般写的埃氏筛消耗的时间都是欧拉筛的三倍,但是欧拉筛并不好想(对于我这种蒟蒻) 虽然 -- 我 -- 也可以背过模板,但是写个不会的欧拉筛不如写个简单易懂的埃氏筛 于是就有了优化 这个优化还是比较 ...

  6. 埃氏筛+线段树——cf731F

    从2e5-1依次枚举每个数作为主显卡,然后分段求比它大的数的个数,这里的复杂度是调和级数ln2e5,即埃氏筛的复杂度.. #include<bits/stdc++.h> using nam ...

  7. 数论(8):min_25 筛(扩展埃氏筛)

    min_25 筛介绍 我们考虑这样一个问题. \[ans=\sum_{i = 1}^nf(i)\\ \] 其中 \(1 \le n \le 10^{10}\) 其中 \(f(i)\) 是一个奇怪的函数 ...

  8. Sirni题解(最小生成树,埃氏筛)(继 Liang-梁)

    目录 前言 题意 思路 一些建议 前言 本篇是对Liang-梁的Sirni(最小生成树,埃氏筛)的后继博客. 通篇原文:https://blog.csdn.net/qq_37555704/articl ...

  9. hdu.5212.Code(莫比乌斯反演 && 埃氏筛)

    Code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

随机推荐

  1. 渗透测试之信息收集(Web安全攻防渗透测试实战指南第1章)

    收集域名信息 获得对象域名之后,需要收集域名的注册信息,包括该域名的DNS服务器信息和注册人的联系方式等. whois查询 对于中小型站点而言,域名所有人往往就是管理员,因此得到注册人的姓名和邮箱信息 ...

  2. 日志分析平台ELK之日志收集器filebeat

    前面我们了解了elk集群中的logstash的用法,使用logstash处理日志挺好的,但是有一个缺陷,就是太慢了:当然logstash慢的原因是它依赖jruby虚拟机,jruby虚拟机就是用java ...

  3. 小白也能看懂的ArrayList的扩容机制

    来,话不多说进入正题!我们下面用最简单的代码创建ArrayList并添加11个元素,并 一 一 讲解底层源码:在说之前,给大家先普及一些小知识: >ArrayList底层是用数组来实现的 > ...

  4. 解决Dubbo无法发布被事务代理的Service问题

    在HelloServiceImpl类上加入@Transactional注解后,虽然工程可以正常跑起来,但是通过dubbo管理控制台可以看到里面并没有服务发布上来. 此时启动服务提供者和服务消费者,并访 ...

  5. Opencv的imread用法

    所有参考来自网上仅仅做学习记录用,具体正确性需要在具体项目各自验证,不涉及具体错误代码处理调试等问题,欢迎发现发现问题~ 参考: 1. https://blog.csdn.net/LiheZhu/ar ...

  6. JS/TS 对数组中的对象按对象的值进行去重

    举个例子:对以下数组按 lastName 的值进行去重 let listData = [ { firstName: "Rick", lastName: "Sanchez& ...

  7. DM8数据库备份还原的原理及应用

    (本文部分内容摘自DM产品技术支持培训文档,如需要更详细的文档,请查询官方操作手册,谢谢) 一.原理 1.DM8备份还原简介 1.1.基本概念 (1)表空间与数据文件 ▷ DM8表空间类型: ▷ SY ...

  8. BeetleX之webapi使用入门

    BeetleX是TCP通讯应用组件,在它之上可以扩展任何基于TCP的应用通讯功能.FastHttpApi是组件扩展的一个Http/Https/Websocket服务组件,它提供的功能丰富,包括功能有: ...

  9. Docker开启远程连接,本地IDEA使用docker插件连接(不认证的版本和认证的版本都有)

    前言 在学校学习的时候,要部署一个Java程序,一般是打成war包,放到服务器上的tomcat的webapp里面去: 后来SpringBoot出现内置了tomcat,就直接打成jar包,丢到服务器任何 ...

  10. 【5】进大厂必须掌握的面试题-Java面试-spring

    spring面试问题 Q1.什么是spring? Spring本质上是一个轻量级的集成框架,可用于用Java开发企业应用程序. Q2.命名Spring框架的不同模块. 一些重要的Spring Fram ...