zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 80 (Rated for Div. 2)

    前言

    D 题看起来就像是二分,但不知道怎么写 check ,而且二分不熟……每次写二分的时候都担惊受怕。干脆花了一晚上总结了一下各种二分的写法。以后写二分应该没有那么慌了。
    二分的总结明天或后天再写吧。留个坑在这里。

    限时只做了 A、B、C 三题,D 题后面补了。 E、F 题估计是不补了。以后有机会再康康吧。

    比赛链接


    题解

    A. Deadline

    题目大意

    给定 (n, d) 判断是否存在一个整数 (x) 使得 (x + lceildfrac{d}{x + 1} ceil le n)

    分析

    一波数学推导有:

    [x + lceildfrac{d}{x + 1} ceil = x + 1 + lfloordfrac{d}{x + 1} floor = lfloor x + 1 +dfrac{d}{x + 1} floor ge lfloor2sqrt{d} floor ]

    当且仅当 ((x + 1)^2 = d) 也就是 (x = sqrt d - 1) 的时候取得最小值。
    直接算出 (x)(x + 1)(x + lceildfrac{d}{x + 1} ceil) 的值,代入与 (n) 判断即可。

    代码

    B. Yet Another Meme Problem

    题目大意

    给定 (A, B) 找出所有的二元组 (1 le a le A)(1 le b le B) 使得(a cdot b + a + b = conc(a, b)),其中 (conc(a, b)) 是将 (a, b) 直接相连起来。例如 (conc(12, 23) = 1223)(conc(100, 11) = 10011)

    分析

    不妨设 b 的位数为 (n) ,那么有:

    [ab + a + b = 10^ncdot a + b Rightarrow b = 10^n - 1 ]

    枚举算一下在小于 (B) 时有多少个 (b) 满足 (10^n - 1) 算出 (n) 。再乘以 (A) 即可。

    代码

    C. Two Arrays

    题目大意

    给定数组长度 (m) ,和数字范围 ([1,n]) 构造两个数组,使得 (a) 数组不降,(b) 数组不升。且对于两个数组每个元素,都有 (a_i le b_i) 。询问有多少种构造方法?

    分析

    (a) 数组不降,(b) 数组不升,且 (a_i le b_i) ,那么 (a_{max} le b_{min}) ,所以我们不妨枚举 (b_{min})

    (dp_1[t][m])(a) 数组中,第 (m) 个空填数字 (t) 的方法数,那么显然有:

    [dp_1[t][m] = sum_{i = 1}^tdp_1[i][m - 1] ]

    边界为:

    [dp_1[t][1] = 1 ]

    对于 (b) 数组类似,有

    [dp_2[t][m] = sum_{i = t}^ndp_2[i][m - 1] ]

    边界为:

    [dp_2[t][1] = 1 ]

    所以,对于确定的 (b_{min}) 的总的构造方法数为 (dp_2[b_{min}][m] cdot sum_{i = 1}^{b_{min}}dp_1[i][m])。用记忆化优化总的时间复杂度为 (O(n^2))

    听说这题还能用组合数学直接得出公式,留坑待填。

    代码

    D. Minimax Problem

    题目大意

    给定 (n) 个数组,每个数组长度为 (m) ,要找到其中的两个数组 (a, b) ,构成一个新的数组 (c) , 其中 (c_i = max(a_i, b_i)) ,使得数组 (c) 的最小值最大。

    分析

    最大化最小值,一看就很有二分的味道。然而我想了半个小时没想出来。无奈只能求助 wj 。wj 很快就给出了一个二分的解法(wjnb!!)。具体思路是这样的:

    假设我们找到的最大的最小值为 (x) 那么对于每个数组的每个元素,我们把大于等于 (x) 的值变成 (1) ,小于的变成 (0) 这样就构成了一个二进制串。然后留意到 (m) 最大只有 (8) 那么可以状压一下,开个数组记录一下这个序列出现过。

    然后对于每个数组的二进制串,我们只要找到另外一个二进制串( (m) 只有 (8) 直接枚举长度为 (m) 的所有串,再用数组判断有没有出现过即可),使得这两个串位或起来全为 1 即可。

    在二分找到最大的最小值 (x) 后,再重复一次上面的操作就能得到是哪两个数组了。

    代码

  • 相关阅读:
    linux启动流程
    监控命令
    ansible组
    公钥和秘钥
    SSH协议介绍
    Java并发编程笔记之ThreadLocal内存泄漏探究
    【死磕 Java 集合】— ConcurrentSkipListMap源码分析
    GraphX介绍
    Storm内部的消息传递机制
    JanusGraph Server配置
  • 原文地址:https://www.cnblogs.com/ljxtt/p/12204008.html
Copyright © 2011-2022 走看看