HDU 4430Yukari's Birthday2012现场赛K题(幂打表 思维 枚举+二分)

Yukari's Birthday

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1373    Accepted Submission(s): 267


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 k i 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 ≤ 10 12.
 

Output
For each test case, output r and k.
 

Sample Input
   
   
   
   
18 111 1111
 

Sample Output
   
   
   
   
1 17 2 10 3 10
 

                      题目大意:题目意思很好懂,只是数据范围很大。而且10000组数据动不动就TLE.反正昨天是没怎么想,六级过了,有点小激动。

            解题思路:开始一直想的是枚举k,然后找到最接近的k+k^2+......+k^r=n或n-1.两边同时取对数,然后求得r最小是ln((n-1)*(k-1)+k)/ln(k)-1然后从这里开始枚举,如果>n就跳出来。这样是10^6的复杂度,但是10000组数据而且要用到取对数快速幂直接果断TLE了。然后r=2的时候先拿出来讨论,这样就变成了10^4的复杂度,但是最后还是由于用到了取对数TLE了。最后小吉吉直接果断把求幂打表,很牛叉的过了,此处应该有掌声。

            昨天下来自己想了一下,r貌似最大才五六十的样子。写了一下发现2^40就超过了10^13觉得可以直接枚举r然后二分求k.不过从TLE,到WA,然后是除0爆栈,最终能AC不容易。这个题目今天一上午都在搞,真的是WA出翔了。这个题目借用了求幂打表的思想。具体思路见代码。

           题目地址:Yukari's Birthday

AC代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
using namespace std;
__int64 n,i,j,l;
__int64 r,k,rk;

//__int64 res=pow(2,39);
//printf("%I64d\n",res);
//1099511627776

__int64 pow1[10002][65];  //对求幂打表
int main()
{

    for(i=2;i<=10000;i++)
        pow1[i][1]=i;
    for(i=2;i<=10000;i++)
    {
        for(j=2;j<=40;j++)
        {
           pow1[i][j]=pow1[i][j-1]*i;
           if(pow1[i][j]>1e17)  //这个地方以免爆int64
              pow1[i][j]=0;
        }
    }

    while(~scanf("%I64d",&n))
    {
        r=1,k=n-1,rk=r*k;  //r=1;

        __int64 t1=sqrt((n-1)*1.0);
        for(i=t1;i<=1000000;i++)  //r=2;枚举k
        {
            __int64 tmp=i*i+i;
            if(i>rk||tmp>n)
                break;
            if(tmp==n||tmp==n-1)
            {
                r=2,k=i,rk=r*k;
                break;
            }
        }

        for(j=3;j<=39;j++)  //枚举r 二分K
        {
            int left=2; int right=10000;
            int mid;
            while(left<right)
            {
                mid=(left+right)>>1;
                __int64 tmp;
                if(pow1[mid][j+1]==0)  //处理刚才爆int64的地方
                {
                   right=mid-1;
                   continue;
                }
                tmp=(pow1[mid][j+1]-mid)/(mid-1);
                if(tmp==n-1||tmp==n)
                {
                   if(mid*j<rk||(mid*j==rk&&j<r))
                      r=j,k=mid,rk=r*k;
                   break;
                }
                if(tmp<n-1)
                    left=mid+1;
                else
                    right=mid-1;
            }
            
            __int64 tmp;
            mid=(left+right)>>1;  //还要再检查一下mid,跳出来的情况没判断
            tmp=(pow1[mid][j+1]-mid)/(mid-1);

            if(tmp==n-1||tmp==n)
            {
                if(mid*j<rk||(mid*j==rk&&j<r))
                {
                    r=j,k=mid,rk=r*k;
                }
            }
        }

        printf("%I64d %I64d\n",r,k);
    }
    return 0;
}
//78MS 5332K


第一次能排个名次,截个图
HDU 4430Yukari's Birthday2012现场赛K题(幂打表 思维 枚举+二分)_第1张图片

你可能感兴趣的:(思维,打表)