这道题是我大一时做的,一直TLE,最近没事,有找出来看看,仍然悲剧的TLE,无奈只好求助于其他大神,终于明白了其中的原因。
大体思路:题目并不算难,只是有些需要注意的地方。因为数据范围较大,所以不能简单的枚举,需要近似算出一个结果。通过题意分析,我们可以得到公式:v*[(k^p-1)/k^(p-1)*(k-1)]>=n。然后将(k^p-1)/k^(p-1)*(k-1)放大得到k/(k-1),不过其实在放大之前按照上面这个公式计算,(k^p-1)/k^(p-1)*(k-1)已经比按题意计算要大,因为题目里除法都是整除,而这里是数学的等比数列求和公式,不会把小数丢掉,当然这不是此题关键。此时我们已经得到近似于结果的v了,然后根据v<k^p,就可以得出结果了。
需要注意的地方:前面的思路我想大家都没问题,关键是要注意此题的数据范围较大,如果不注意很容易爆掉。主要注意两个地方,一是估算v的时候,如果v是int类型,还用v=n*(k-1)/k,那么你一定TLE,二是下面这种情况:
while(true)
{
sum=v;
t=k;
while(v>=t)
{
sum+=v/t;
t*=k;
}
if(sum>=n) break;
v++;
}
在n=10^9,k=9时,t也会爆掉。该注意的地方差不过就这些~
最后,索性总结一下我自己认为会TLE的一些情况。第一,可能是算法问题,复杂度太高;第二,可能有死循环;第三,当你用scanf读入数据,需要用EOF结束输入时你没用;第四,就是此题的情况,没有注意数据范围,计算时爆掉了,导致数字变成负数,与正确答案相差甚远,导致超时。欢迎大家补充其他情况~
代码(G++):
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int n,k,v,sum,t;
while(scanf("%d %d",&n,&k)!=EOF)
{
v=1.0*n/k*(k-1);
while(true)
{
sum=0;
t=v;
while(t>0)
{
sum+=t;
t/=k;
//cout<<"t = "<<t<<endl;
}
if(sum>=n) break;
v++;
}
printf("%d\n",v);
}
return 0;
}
题目( http://acm.hfut.edu.cn/OnlineJudge/):
敲代码
Time Limit: 1000 MS | Memory Limit: 65536 KB |
Description
Input
Output
Sample Input
59 9
Sample Output
54
Hint
对于第二组数据,他开始先写54行代码,接着他写6行,然后devtang就入睡了,故总共写了54+6=60>59。