zoukankan      html  css  js  c++  java
  • 【文文殿下】CF1029F Multicolored Markers

    这道题考场上卡了文文相当长的时间,所以写个题解泄泄愤QAQ

    题意:给你$a$块红瓷砖,$b$块白瓷砖,在一个无限大的地上拼装,要求整体是一个矩形,并且至少有一种颜色是一个矩形,求最小周长。


    题解:

      首先,我们知道,当面积一定时,矩形的形状越接近正方形,周长越小。

      很显然的想到,我们可以给总数$tot$=$a$+$b$开个方,然后去找一个最接近的矩形出来。

      但事实上这个方法是错误的:你无法保证至少有一种颜色的是一个矩形。

      我们首先,要分情况讨论,让$a$是矩形还是让$b$是矩形。当然,我们讨论每个的时候,不约束另一个的形状。

      假设我们保证$a$是矩形,那么我们就要首先找出从$1$到$sqrt{a}$之间所有的$a$的因数,来找到$a$矩形的较短边。

      然后再找总数的较短边。

      我们每找到一个总数的较短边$x$,就要在$a$的因数中,找到最大的一个小于$x$的数字。这一步可以用一个$splay$维护,当然由于是静态的,也可以二分查找。

      但事实上,有一个显而易见的规律:如果我们从小到大枚举$tot$的因数,那么对应的$a$的因数是单调的。所以我们利用这个单调性,缩短到$O(a)$.

      然后对$b$ ,Once More! 找两者的最优解

      参考代码

      

    #include <bits/stdc++.h>
    
    #define forn(i, n) for (int i = 0; i < int(n); i++)
    
    typedef long long li;
    
    using namespace std;
    
    const int N = 1000 * 1000;
    
    int lens[N];
    int k;
    
    li solve(li a, li b){
        k = 0;
        for (li i = 1; i * i <= b; ++i)
            if (b % i == 0)
                lens[k++] = i;
        
        li ans = 2 * (a + b) + 2;
        li x = a + b;
        int l = 0;
        for (li i = 1; i * i <= x; ++i){
            if (x % i == 0){
                while (l + 1 < k && lens[l + 1] <= i)
                    ++l;
                if (b / lens[l] <= x / i)
                    ans = min(ans, (i + x / i) * 2);
            }
        }
        
        return ans;
    }
    
    int main() {
        li a, b;
        scanf("%lld%lld", &a, &b);
        printf("%lld
    ", min(solve(a, b), solve(b, a)));
        return 0;
    }
    View Code
  • 相关阅读:
    学习方法
    Python——语言基础
    JSP——JavaServer Page中的隐式对象(implicit object)、指令(directive)、脚本元素(scripting element)、动作(action)、EL表达式
    Socket——实现一个简单的静态网页服务器
    CSS效果——绝对居中
    Java——重写hashCode()和euqals()方法
    Java操作符——i++ 和 ++i的区别
    JDBC——数据库连接池以及JDBC代码模版模版
    JDBC——DBHelper代码模版
    JDBC——JDBC基础
  • 原文地址:https://www.cnblogs.com/Syameimaru/p/9548383.html
Copyright © 2011-2022 走看看