zoukankan      html  css  js  c++  java
  • HDU 4430 二分查找


    Yukari's Birthday
    Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5071    Accepted Submission(s): 1199


    Problem Description
    Today is Yukari's n-th birthday. Ran and Chen hold a celebration party for her. Now comes the most important part, birthday cake! But it's a big challenge for them to place n candles on the top of the cake. As Yukari has lived for such a long long time, though she herself insists that she is a 17-year-old girl.
    To make the birthday cake look more beautiful, Ran and Chen decide to place them like r ≥ 1 concentric circles. They place ki candles equidistantly on the i-th circle, where k ≥ 2, 1 ≤ i ≤ r. And it's optional to place at most one candle at the center of the cake. In case that there are a lot of different pairs of r and k satisfying these restrictions, they want to minimize r × k. If there is still a tie, minimize r.
     

    Input
    There are about 10,000 test cases. Process to the end of file.
    Each test consists of only an integer 18 ≤ n ≤ 1012.
     

    Output
    For each test case, output r and k.
     

    Sample Input
    18 111 1111
     

    Sample Output
    1 17 2 10 3 10
     

    题意:摆一圈一圈的蜡烛,中间的一个蜡烛可放可不放,不算圈数,层数为r,每层的蜡烛数为k^(1~r),k ≥ 2, 1 ≤ i ≤ r.给一个数,输出r*k最小的k和r。

    由于当时老胡负责这个题目,所以把直接把他代码搬过来了:老胡传送门 老胡:http://www.cnblogs.com/pach/p/5759809.html

    给出n,让n满足下列表达式:k^1+k^2+...+k^r=n. 且r*k要最小。(ps: And it's optional to place at most one candle at the center of the cake. 所以k^0,即1可有可无。但是这并不算一个圆,所以当n=30和n=31时,它们的r相等)  例如:2^1+2^2+2^3+2^4=30. n=30,r=4,k=2. (n=31时,r也为4,k也为2)  所以就有通解r=1,k=n-1. 这对于每个n都成立。不过我们得让r*k最小,就得都遍历一遍了。
    因为2^0+2^1+2^2+...+2^40=2^41-1>10^12. 所以1<=r<=40. r不是很大,直接暴力。k通过二分来找。

    当时考虑到一种情况就是当r>=2的时候,k的最大值是n-1,n最大为10^12,所以k=10^12-1,k^0+k^1+k^2<=n,所以二分查找k的时候直接从high=100w开始。(100w的平方为2的12次方),但是提交的时间并没有缩短反而增加,为什么?

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    const long long inf=1000000000001;
    int main()
    {
        //freopen("in.txt","r",stdin);
        long long n;
        while(scanf("%I64d",&n)!=EOF)
        {
            int min_r;
            long long min_k,min_v=inf;
            for(int r=1; r<=40; r++)
            {
                long long low=1,high=n,k; //每一次r的更新,都要进行一次完整的二分查找
                while(1)
                {
                    k=(low+high)/2;
                    long long sum=0;
                    bool flag=true;
                    //此处是关键,由于数值很大,直接判断值是否超出n,如果用sum的方法判断又多了内存,其实在int64位后面多一位的相加直接可以忽略少一位的数值了
                    for(int i=1; i<=r; i++)
                        if(pow(k*1.0,i)>n) //此处是判读那看k^i是否大于n,如果大于,就不用再求和了
                        {
                            sum=n+1;
                            flag=false;
                            break;
                        }
                    if(flag)
                        for(int i=1; i<=r && sum<=n; i++)
                            sum+=(long long)pow(k*1.0,i);
                    if(sum==n || sum==n-1) //因为1可有可无,所以满足其中一个条件即可
                        if(r*k<min_v)
                        {
                            min_r=r;
                            min_k=k;
                            min_v=r*k; //保存最小乘积
                        }
                    if(sum>n)
                        high=k;//sum大了则从左边找
                    else
                        low=k; 
                    if(high-low==1)
                        break;
                }
            }
            printf("%d %I64d
    ",min_r,min_k);
        }
        return 0;
    }
    
    还有就是这题右边的查找范围可能溢出,需要考虑。

  • 相关阅读:
    Kafka 生产者 自定义分区策略
    同步互斥
    poj 1562 Oil Deposits(dfs)
    poj 2386 Lake Counting(dfs)
    poj 1915 KnightMoves(bfs)
    poj 1664 放苹果(dfs)
    poj 1543 Perfect Cubes (暴搜)
    poj 1166 The Clocks (暴搜)
    poj 3126 Prime Path(bfs)
    处理机调度
  • 原文地址:https://www.cnblogs.com/mingrigongchang/p/6246225.html
Copyright © 2011-2022 走看看