题目链接:
HDU:http://acm.hdu.edu.cn/showproblem.php?pid=4430
ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4888
18 111 1111
1 17 2 10 3 10
题意:
要在一个蛋糕上放置 n 根蜡烛,摆成 r 个同心圆,每个同心圆的蜡烛数为 k ^ i ,中间的圆心可以放一根或者不放,使得 r * k 最小,若有多个答案输出 r 最小的那个。
PS:
因为r是很小的 !
枚举r查找k!
代码如下:(HDU,ZOJ上把64位换为long long就OK啦……)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
//typedef long long LL;
typedef __int64 LL;
#define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
LL n;
LL findd(LL m)
{
LL l, r, mid;
l = 2;
r = n;
while(l <= r)
{
mid = (l+r)/2;
LL sum = 0, tt = 1;
for(LL i = 1; i <= m; i++)
{
if(n/tt < mid)//注意可能溢出用除法判断一下
{
//tt*mid > n
sum = n+1;
break;
}
tt*=mid;
sum += tt;
// if(sum > n)//防止溢出
// break;
}
if(sum == n-1 || sum == n)
{
return mid;
}
if(sum < n-1)
{
l = mid+1;
}
else if(sum > n)
{
r = mid-1;
}
}
return -1;//没有符合的
}
int main()
{
LL r, k, rr, kk;
while(~scanf("%I64d",&n))
{
rr = r = 1;
kk = k = n-1;
for(LL i = 2; i <= 64; i++)
{
LL tt = findd(i);
// if(i >= n)
// break;
// printf("tt:%I64d>>>%I64d\n",i,tt);
if(i*tt < rr*kk && tt != -1)
{
r = i;
k = tt;
rr = i;
kk = tt;
}
}
printf("%I64d %I64d\n",r,k);
}
return 0;
}
/*
18
111
1111
1022
8190
134217726
34359738366
68719476734
*/
HDU 4430 & ZOJ 3665 Yukari's Birthday(二分+枚举)
原文地址:http://blog.csdn.net/u012860063/article/details/40947547