zoukankan      html  css  js  c++  java
  • 【19.05%】【codeforces 680D】Bear and Tower of Cubes

    time limit per test2 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard output
    Limak is a little polar bear. He plays by building towers from blocks. Every block is a cube with positive integer length of side. Limak has infinitely many blocks of each side length.

    A block with side a has volume a3. A tower consisting of blocks with sides a1, a2, …, ak has the total volume a13 + a23 + … + ak3.

    Limak is going to build a tower. First, he asks you to tell him a positive integer X — the required total volume of the tower. Then, Limak adds new blocks greedily, one by one. Each time he adds the biggest block such that the total volume doesn’t exceed X.

    Limak asks you to choose X not greater than m. Also, he wants to maximize the number of blocks in the tower at the end (however, he still behaves greedily). Secondarily, he wants to maximize X.

    Can you help Limak? Find the maximum number of blocks his tower can have and the maximum X ≤ m that results this number of blocks.

    Input
    The only line of the input contains one integer m (1 ≤ m ≤ 1015), meaning that Limak wants you to choose X between 1 and m, inclusive.

    Output
    Print two integers — the maximum number of blocks in the tower and the maximum required total volume X, resulting in the maximum number of blocks.

    Examples
    input
    48
    output
    9 42
    input
    6
    output
    6 6
    Note
    In the first sample test, there will be 9 blocks if you choose X = 23 or X = 42. Limak wants to maximize X secondarily so you should choose 42.

    In more detail, after choosing X = 42 the process of building a tower is:

    Limak takes a block with side 3 because it’s the biggest block with volume not greater than 42. The remaining volume is 42 - 27 = 15.
    The second added block has side 2, so the remaining volume is 15 - 8 = 7.
    Finally, Limak adds 7 blocks with side 1, one by one.
    So, there are 9 blocks in the tower. The total volume is is 33 + 23 + 7·13 = 27 + 8 + 7 = 42.

    【题解】

    递归求解;
    一层层地减少问题的规模;
    类似分治的思想;
    dfs(int w);表示m=w的时候问题的解是什么;
    一开始的时候调用dfs(m);
    然后,对于”当前”的w(也即这个子问题中的m);
    我们有两种决策
    1.直接取最大的;
    则我们找到最大的p;
    满足p^3<=w;
    然后体积递增p^3,方块数递增1,递归求解dfs(w-p^3);
    也即m变成了w-p^3,体积可以是1..w-p^3中的任意的最优解;
    2.不直接取最大的;换成取中间的某个数字;
    对p考虑;
    这里的p仍然是上面的p;
    我们可以递归求解dfs(p^3-1);
    这样,下一层递归里面选最大的就会变成选(p-1)^3;
    再往下递归一层就是dfs(p^3-1 - (p-1)^3);
    而当我们递归dfs(p^3-1 - (p-1)^3)的时候,方块的数目也只是1;
    而dfs(p^3-1 - (p-1)^3)不一定就比dfs(w-p^3)(调用时方块数也是1)大,则我们先比较一下这两个值的大小。如果前者大于后者。则说明前者有可能弄出来更优的解。否则的话就没必要递归dfs(p^3-1);
    那有没有可能调用递归dfs((p-1)^3-1)呢?答案是否定的;
    因为
    f(p) = p^3 - 1 - (p-1)^3在0到正无穷上是一个单调递增的函数;
    则dfs((p-1)^3-(p-2)^3)肯定不能弄出比dfs(p^3-1-(p-1)^3)更优的答案;
    快速找出那个p可以用二分;
    还不理解就多想想吧。
    这题想了挺久的。上面也只是我自己的理解。

    #include <cstdio>
    #include <map>
    #include <vector>
    #define LL long long
    
    using namespace std;
    
    LL m;
    pair <LL, LL> ans;
    map <LL, pair<LL, LL> > fre;
    
    LL get_max(LL x)
    {
        LL l = 1, r = (1e5 + 10);
        LL ans;
        while (l <= r)
        {
            LL mid = (l + r) >> 1;
            LL t = mid*mid*mid;
            if (t <= x)
            {
                ans = t;
                l = mid + 1;
            }
            else
                r = mid - 1;
        }
        return ans;
    }
    
    pair <LL, LL> dfs(LL x)
    {
        if (x == 0)
            return make_pair(0, 0);
        if (fre.count(x))
            return fre[x];
        pair <LL, LL> &temp = fre[x];
        LL p3 = get_max(x);
        temp.first = 0;
        temp = dfs(x - p3);
        temp.first++;
        temp.second += p3;
        pair <LL, LL> temp2;
        LL t2 = 0;
        if (p3 - 1 > 0)
        {
            t2 = p3 - 1 - get_max(p3 - 1);
        }
        if (t2 > (x - p3))
            temp2 = dfs(p3 - 1);
        else
            temp2.first = 0;
        if (temp2.first > temp.first)
            temp = temp2;
        return temp;
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        scanf("%I64d", &m);
        ans = dfs(m);
        printf("%I64d %I64d
    ", ans.first, ans.second);
        return 0;
    }
  • 相关阅读:
    八字案例董易奇
    nginx和tomcat二合一服务器配置SSL证书
    RecyclerView,内容不居中的解决办法。
    cxf接口生成WSDL带密码的code实践
    去除server.key的密码
    Window下openssl的安装教程(通俗易懂)
    Nginx配置https证书
    自己做CA
    自己生成ssl证书
    自己制作ssl证书:自己签发免费ssl证书,为nginx生成自签名ssl证书
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632130.html
Copyright © 2011-2022 走看看