每日一题 | 二进制操作问题
昨日题解
每日一题 | 灾后重建问题
codeforces联想杯D题,链接:https://codeforces.com/gym/102623/problem/D
给定m条边,让我们将n个点全部连通,这是一个很明显的最小生成树问题。但是有两个棘手的点,第一个点是每条边的长度不确定,是斐波那契数列算出来的。第二个点是我们希望得到的度最小,但最小生成树的解法并不一定唯一。
所以整个问题的核心就是分析一下上面这两个问题,只要这两个问题解决了,剩下的都好办了。首先来说第一个问题,虽然斐波那契数列并不难求,只需要递推就可以了,但问题是这里的n的范围比较大,对应的斐波那契数列的值是天文数字,我们是不可能存储得下来的。但是我们分析一下,会发现其实我们没有必要计算出具体的值。因为题目当中的序号是从1开始的,那么我们就可以保证每个点的值都各不相同。
并且斐波那契数列有一个性质是从第三个数开始,每个数等于前面两个数的和。首先,我们可以知道这个数列是递增的,其次,我们知道题目当中的一条边的长度等于连接的两个点的斐波那契数列之和,我们假设一条边连接的点是(a, b),另外一条边是(c, d)。那么我们怎么比较这两条边的大小呢?
其实很简单,我们假设a > b, c > d,如果a > c,那么第一条边大,否则第二条边大。我们做一个极端的假设,假设c = a-1, d = a-2,那么根据斐波那契数列的性质可以得到fib(a) = fib(c) + fib(d),但是由于fib(b)至少大于0,所以fib(a) + fib(b) > fib(c) + fib(d)。
也就是说我们根本没必要求出每条边具体对应的值,直接用序号比较大小就可以。另外我们还可以得到一个结论就是,这个图当中的每一条边的长度都各不相同。既然如此,我们进一步可以得到,对应的最小生成树是唯一的。既然如此就很简单了, 我们跑一下最小生成树,然后计算一下每个点的度数即可。
放上不能AC的代码(Python天然比C++慢,导致过不了本题)
class DisjointSet:
def __init__(self, element_num=None):
self._father = [i for i in range(element_num + 2)]
self._rank = [0 for _ in range(element_num + 2)]
def _query(self, x):
if self._father[x] == x:
return x
self._father[x] = self._query(self._father[x])
return self._father[x]
def merge(self, x, y):
x = self._query(x)
y = self._query(y)
if x == y:
return
if self._rank[x] < self._rank[y]:
self._father[x] = y
else:
self._father[y] = x
if self._rank[x] == self._rank[y]:
self._rank[x] += 1
def same(self, x, y):
return self._query(x) == self._query(y)
n, m = map(int, input().split(' '))
edges = []
for _ in range(m):
u, v = map(int, input().split(' '))
l = (u, v) if u > v else (v, u)
edges.append((u, v, l))
disjoint_set = DisjointSet(n+2)
edges = sorted(edges, key=lambda x: x[2])
degrees = [0 for _ in range(n+2)]
ret = 0
for e in edges:
u, v = e[0], e[1]
if disjoint_set.same(u, v):
continue
disjoint_set.merge(u, v)
degrees[u] += 1
degrees[v] += 1
ret = max(ret, degrees[u], degrees[v])
print(ret)
今日问题
二进制操作问题
给定两个非负整数的数组,第一个数组A有n个数,第二个数组B有m个数。对于第一个数组A中的每一个数,你需要从B数组当中选一个数来得到,其中,这里的&表示二进制中的与操作。
对于所有的,我们需要计算,这里的|表示的或操作,要求这样得到最小的d。
- END -
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- nginx的location、rewrite玩法详解
- Redis Lua脚本调试
- 安装elasticsearch 5.x, 6.x 常见问题(坑)的解决
- 轻松搞懂elasticsearch概念
- 深入Golang调度器之GMP模型
- 深入Golang之sync.Pool详解
- 一次对电视盒子的漏洞分析
- MQ选型之RabbitMQ
- httprouter与 fasthttp 的性能对比
- Nmap 脚本研究
- Nmap NSE 库分析 >>> http
- Nmap NSE 库分析 >>> httpspider
- Nmap NSE 库分析 >>> url
- Go语言中的byte和rune区别、对比
- Nmap NSE 缺陷