题目链接:http://codeforces.com/problemset/problem/689/C
题目大意:
有4个小偷去偷巧克力,第一个人偷a个,后面每一个人偷的数目是前一个人的k倍(k>1)。
有谣言说,小偷有m种偷法
(1≤m≤1015)
,请问最后一个人至少偷了多少个巧克力,才能保证偷法恰有m种?
例如:m=1,则偷法只有1种的情况只能是{1,2,4,8},则最后一个人至少偷了8块。
题目分析:
其实是相当于这样一个数学问题:给出m,求n,使得集合
{(a,k)|ak3≤n,a≥1,k≥2,a,k∈Z}
的元素个数恰好为m。
那么因为
ak3≤n
,所以显然
k≤n√3
又有
k≥2
,而对每一个k,又有
1≤a≤nk3
,所以我们有
∑k=2n√3nk3=m
接下来就是在[1,1e20]二分查找n值即可。二分查找用时O(1),(因为查找范围是已知数,所以查找是常数时间),二分里面有一个求和,是O(n^1/3)的。因为n不超过m也就是
1015
,所以问题得解。(一般的oj处理能力为每秒10^8数据量,通常为限时1s)
ac代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll cal(ll n) {
ll sum=0;
for(ll i=2;i*i*i<=n;i++) {
sum+=n/(i*i*i);
}
return sum;
}
int main() {
ll m;
scanf("%I64d", &m);
ll l=0,r=1e16,ans=-1;
while(l<r) {
ll mid=(l+r)/2;
ll temp=cal(mid);
// cout<<mid<<' '<<temp<<endl;
if(temp>m)
r=mid-1;
else if(temp==m)
r=mid;
else
l=mid+1;
}
if(cal(l)==m)
ans=l;
printf("%I64d\n", ans);
}
一开始写二分查找的时候,由于不太熟练,不知道如何去寻找二分的边界,例如输入8-14的时候都返回1,但8是答案。所以要用到寻找下界的二分查找。关于二分查找的边界、范围讨论可以参考博客http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html和http://www.acmerblog.com/ubiquitous-binary-search-5345.html毕竟二分查找作为数据结构中一个十分基础和重要的算法,在面试中应该也很容易被考察到。