[wikioi1553]互斥的数(数学分析+散列/数学分析+二分)
题目描述 Description
有这样的一个集合,集合中的元素个数由给定的N决定,集合的元素为N个不同的正整数,一旦集合中的两个数x,y满足y = P*x,那么就认为x,y这两个数是互斥的,现在想知道给定的一个集合的最大子集满足两两之间不互斥。
输入描述 Input Description
输入有多组数据,每组第一行给定两个数N和P(1<=N<=10^5, 1<=P<=10^9)。接下来一行包含N个不同正整数ai(1<=ai<=10^9)。
输出描述 Output Description
输出一行表示最大的满足要求的子集的元素个数。
样例输入 Sample Input
4 2
1 2 3 4
样例输出 Sample Output
3
数据范围及提示 Data Size & Hint
分析:
我们先通过特殊情况找找规律,如P=2时候(我们假设初始集合足够大)
2->2*2->2*2*2->2*2*2*2->……
3->3*2->3*2*2->3*2*2*2->……
5->5*2->5*2*2->5*2*2*2->……
……
从上面的我们可以看出a*p^(b-1)影响a*p^b(如果存在),而a*p^b影响a*p^(b+1)……,我们假设这样的序列叫做“影响序列”
————————————————————————————————————————————————————
特别注意:
①影响序列中P的次数是连续的
如原数组是6 12 24 96,p=2
则原数组有2个影响序列:(6,12,24)和(96),因为中间缺少了48所以第一个影响序列与第二个影响序列不能合并
②影响序列是完整的
如6 12 24 96,p=2
不能说原数组有3个影响序列(6,12)(24)(96)或(6)(12,24)(96),因为前面两个影响序列可以合并成一个更完整的
——————————————————————————————————————————————————————————
易得出关于 影响序列 的一些性质:
① 任何一个数组都可以分成若干个 影响序列(特别的影响序列只有一个元素)且不同的影响序列互不影响,即一个影响序列中元素的取舍与另个影响序列元素取舍中互不影响(类比将置换群分成若干个轮换)
② 一个影响序列中的元素对应的P对应的次方是严格递增且连续的,如p=2,底数a=3时,6,12,24是一个影响序列,他们是3*2^1,3*2^2,3*2^3,P上面的次数是1,2,3是连续且严格递增的
③ 由②易得如果一个影响序列在中间的某处断掉了,相当于将这个影响序列变成左右两边两个独立的影响序列,两者互不影响
接下来分析题目:
由性质①我们可以将原数组化成若干个影响序列单独处理(化归思想),于是下面我们考虑如何才处理单独的一个影响序列
让我们来明确一下我们想把一个影响序列处理成什么样子:由题意我们应该是要将这个影响序列中删除最少的数使得这个影响序列中剩余的数互不影响,而由性质①和③我们可以知道不同的影响序列互补影响,且删除一个数相当于把影响序列分裂成两个!!!!,即我们的目标是这个影响序列分裂成尽可能多的单元素影响序列!!!
我们发现我们无论采取怎样的分裂方案,始终是一种分治的思想,到最后,把一个影响序列分成若干个两元素影响序列,然后删除每个其中的一个数就完成了,从宏观来看,也就是说我们对于元素个数为n的影响序列我们采取n/2(向下取整)次删除,也就是删了这么多数。于是我们有一个很重要结论—————————————— 一个n元素影响序列,我们应最少删除n/2(向下取整)个数
好了现在题目就明朗了,我们只要找出对应的每个影响序列就行了,鉴于题目的数据范围很大,我们可以用散列表来表示数组中的每个数,然后对于读入的一个数x,将x加入到x*p的集合中,并给对应的集合个数+1(类似于并查集)
或者还有一种做法就是二分:
先把读入的数组ai排序 计数器初值为n
然后从第一个往后扫,发现ai*p也在集合(二分查找)中就删掉它(打个标记),计数器减一
最后输出~~
在纸上划一划就发现这样的实质也就是将影响序列中连续2个元素中删掉一个,所以是对的。
[wikioi1553]互斥的数(数学分析+散列/数学分析+二分)的更多相关文章
- 数据结构---哈希表的C语言实现(闭散列)
原文地址:https://blog.csdn.net/weixin_40331034/article/details/79461705 构造一种存储结构,通过某种函数(hashFunc)使元素的存储位 ...
- Redis从基础命令到实战之散列类型(Hash)
从上一篇的实例中可以看出,用字符串类型存储对象有一些不足,在存储/读取时需要进行序列化/反序列化,即时只想修改一项内容,如价格,也必须修改整个键值.不仅增大开发的复杂度,也增加了不必要的性能开销. 一 ...
- 线性探测再散列 建立HASH表
根据数据元素的关键字和哈希函数建立哈希表并初始化哈希表,用开放定址法处理冲突,按屏幕输出的功能表选择所需的功能实现用哈希表对数据元素的插入,显示,查找,删除. 初始化哈希表时把elem[MAXSIZE ...
- java加密算法--MD5加密和哈希散列带秘钥加密算法源码
package com.ompa.common.utils; import java.security.MessageDigest; import java.security.NoSuchAlgori ...
- s14 第5天 时间模块 随机模块 String模块 shutil模块(文件操作) 文件压缩(zipfile和tarfile)shelve模块 XML模块 ConfigParser配置文件操作模块 hashlib散列模块 Subprocess模块(调用shell) logging模块 正则表达式模块 r字符串和转译
时间模块 time datatime time.clock(2.7) time.process_time(3.3) 测量处理器运算时间,不包括sleep时间 time.altzone 返回与UTC时间 ...
- PTA 逆散列问题 (30 分)(贪心)
题目链接:https://pintia.cn/problem-sets/1107178288721649664/problems/1107178432099737614 题目大意: 给定长度为 N 的 ...
- python对redis的常用操作 上 (对列表、字符串、散列结构操作)
这里的一切讨论均基于python的redis-py库. 安装使用: pip install redis 然后去获取一个redis客户端: redis_conn = redis.Redis(host=R ...
- [No0000132]正确使用密码加盐散列[译]
如果你是一个 web 开发工程师,可能你已经建立了一个用户账户系统.一个用户账户系统最重要的部分是如何保护密码.用户账户数据库经常被黑,如果你的网站曾经被攻击过,你绝对必须做点什么来保护你的用户的密码 ...
- 【Redis学习之五】Redis数据类型:列表和散列
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 redis-2.8.18 一.列表 基于Linked Lis ...
随机推荐
- C语言的函数
"函数"在英文的翻译是"function",无论在自然科学还是计算机科学都是这个词,而"function"的本意是"功能" ...
- Gulp使用入门操作十一步压缩JS
前提需要安装nodejs 一. 全局安装Gulp npm install -g gulp 二.新建一个 gulpfile.js 文件 chapter2└── gulpfile.js 三.在 gulpf ...
- IOS版本被拒的经历
IOS版本被拒的经历: 1,登陆方式依赖外部平台 因为我们的APP是只用微博登陆,想做成类似meerkat类型的,也能各种消息都同步微博. 结果当然行不通,这个确实是不听好人言,网上多个人都说过这个问 ...
- linux sed命令
一.初识sed 在部署openstack的过程中,会接触到大量的sed命令,比如 # Bind MySQL service to all network interfaces. sed -i 's/1 ...
- 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题
一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的 ...
- NOIP2013普及组 -SilverN
T1 计数问题 题目描述 试计算在区间 1 到 n 的所有整数中,数字 x(0 ≤ x ≤ 9)共出现了多少次?例如,在 1 到 11 中,即在 1.2.3.4.5.6.7.8.9.10.11 中, ...
- docker containerd 中的create 容器操作
containerd的create container的API如下所示: type CreateContainerRequest struct { Id string BundlePath strin ...
- runc的detach, console, tty等相关问题
runc 端解析: 1. runc/utils_linux.go func (r *runner) run(config *specs.Process) (int , error) 在该函数中第一次对 ...
- 手把手教你如何用ZBrush刻画脸部
今天的ZBrush教程我们将参照一张效果图对模型进行脸部刻画.在进入课堂之前我们有必要对Layers层概念和操作有所了解,然后结合之前学习的雕刻笔刷对模型的特征表情给予重点刻画. 详细的视频教程地址请 ...
- NGUI 3.x 练习
一.常用快捷键 Alt+Shitf+W 创建一个新的 Widget Alt+Shift+S 创建一个新的 Sprite Alt+Shift+L 创建一个新的 Label Alt+Shift+T 创建一 ...