/*
HDU - 4430
题目大意就是
给你n个蜡烛
要你围城r个同心圆,每个圆上的蜡烛数是k^i
在圆的中心可以放1个蜡烛也可以不放
问当r*k最小时,r和k分别是多少
解题思路:
我们可以枚举r然后找到符合条件的k
计算r*k找到最小的哪一组
当r最大,则k要最小即k==2
2^0+2^1+2^2+...+2^40=2^41-1>10^12
所以r最大就41,枚举r时枚举到41左右即可不用循环太多次
另外当r=1,k=n-1时是所有n的一个通解
即此题不存在无解的情况
查找k的时候使用二分查找可以减少时间
*/
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<stdio.h>
#include<math.h>
#define ll long long
#define PI acos(-1)
using namespace std;
ll n;
ll work(ll k,int j)
{
ll sum=0;//对k~k^j项求和
ll ans=1;//求k的1~j次方
//此处说明一下,因为编译器的原因pow(10.0,2)会被某些编译器计算成99所以没有直接使用pow函数
for(int i=1; i<=j; i++)
{
if(n/ans<k)//当k的某个次方数超过n时,就已经不满足要求了,所以设置一个标志后直接跳出
{
sum=n+1;//设置的标志,让sum出现一个不应该出现的值
break;
}
ans=ans*k;//若符合要求,则计算k的i次方
sum=sum+ans;//计算k的前i次方的和
if(sum>n)//若sum已经大于蜡烛数则这个k不满足要求,直接跳出
break;
}
return sum;
}
int main()
{
while(cin>>n)
{
ll a=1,b=n-1;//设置一个通解
for(int j=2; j<=45; j++)//对圈数循环
{
ll l=1,r=n;//二分查找设置左右
ll mid;
while(r-l!=1)//循环查找的条件
{
mid=(l+r)/2;
ll sum=work(mid,j);
if(sum==n||sum==n-1)//因为可以在中心摆放一个蜡烛,也可以不摆放所以二者满足其一即可
{
if(mid*j<a*b)//若比以前求得的要小则保存下来
{
a=j;
b=mid;
}
}
if(sum<n-1)//若sum还不够大则将左端点右移,否则右端点左移
l=mid;
else
r=mid;
}
}
cout<<a<<' '<<b<<endl;
}
return 0;
}
HDU - 4430
题目大意就是
给你n个蜡烛
要你围城r个同心圆,每个圆上的蜡烛数是k^i
在圆的中心可以放1个蜡烛也可以不放
问当r*k最小时,r和k分别是多少
解题思路:
我们可以枚举r然后找到符合条件的k
计算r*k找到最小的哪一组
当r最大,则k要最小即k==2
2^0+2^1+2^2+...+2^40=2^41-1>10^12
所以r最大就41,枚举r时枚举到41左右即可不用循环太多次
另外当r=1,k=n-1时是所有n的一个通解
即此题不存在无解的情况
查找k的时候使用二分查找可以减少时间
*/
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<stdio.h>
#include<math.h>
#define ll long long
#define PI acos(-1)
using namespace std;
ll n;
ll work(ll k,int j)
{
ll sum=0;//对k~k^j项求和
ll ans=1;//求k的1~j次方
//此处说明一下,因为编译器的原因pow(10.0,2)会被某些编译器计算成99所以没有直接使用pow函数
for(int i=1; i<=j; i++)
{
if(n/ans<k)//当k的某个次方数超过n时,就已经不满足要求了,所以设置一个标志后直接跳出
{
sum=n+1;//设置的标志,让sum出现一个不应该出现的值
break;
}
ans=ans*k;//若符合要求,则计算k的i次方
sum=sum+ans;//计算k的前i次方的和
if(sum>n)//若sum已经大于蜡烛数则这个k不满足要求,直接跳出
break;
}
return sum;
}
int main()
{
while(cin>>n)
{
ll a=1,b=n-1;//设置一个通解
for(int j=2; j<=45; j++)//对圈数循环
{
ll l=1,r=n;//二分查找设置左右
ll mid;
while(r-l!=1)//循环查找的条件
{
mid=(l+r)/2;
ll sum=work(mid,j);
if(sum==n||sum==n-1)//因为可以在中心摆放一个蜡烛,也可以不摆放所以二者满足其一即可
{
if(mid*j<a*b)//若比以前求得的要小则保存下来
{
a=j;
b=mid;
}
}
if(sum<n-1)//若sum还不够大则将左端点右移,否则右端点左移
l=mid;
else
r=mid;
}
}
cout<<a<<' '<<b<<endl;
}
return 0;
}