题意:n根蜡烛,蛋糕是R层的,每一层可以插k的I次方个蜡烛,然后蛋糕中心可以或不插蜡烛,问R*K最小的情况中R最小的那组答案,且这R层必须插满
思路:因为它一定是插满的,对于一个R层的蛋糕,它的蛋糕上插的蜡烛数量是随着K的增大而增大,满足单调性可以用二分,然后蛋糕层数可知最大不会超过50,那么枚举就行了,简单的二分,但是要注意的是K的i次方是有可能爆long long的,我的判断方法蠢的不行了,因为不会数学找不到更好的方法了,(/ □ \)~~~~
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
ll ans[60],flag;
ll n,len;
int overall(ll t,ll mid){
if((t>=10&&mid>=1000000000000)||(t>=100&&mid>=100000000000)||(t>=1000&&mid>=10000000000)) return 1;
if((t>=10000&&mid>=1000000000)||(t>=100000&&mid>=100000000)||(t>=1000000&&mid>=10000000)) return 1;
if((t>=10000000&&mid>=1000000)||(t>=100000000&&mid>=100000)||(t>=1000000000&&mid>=10000)) return 1;
if((t>=10000000000&&mid>=1000)||(t>=100000000000&&mid>=100)||(t>=1000000000000&&mid>=10)) return 1;
if((t>=10000000000000&&mid>=1)||(t>=1&&mid>=10000000000000)) return 1;
return 0;
}
int judge(int x,ll mid){
ll sum=0,t=mid;
int flag1=0;
for(int i=1;i<=x;i++){
sum+=t;
if(sum>n) return 1;
if(i!=x&&overall(t,mid)) return 1;
t*=mid;
}
if(sum==n||sum==n-1) return 0;
else if(sum<n-1) return 2;
}
void slove(int x){
ll le=0,ri=n+1;
while(ri-le>1){
ll mid=(le+ri)>>1;
int t=judge(x,mid);
if(t==1) ri=mid;
else if(t==0){
ri=mid;
flag=1;len=min(len,mid);
}else if(t==2) le=mid;
}
}
int main(){
while(scanf("%I64d",&n)!=-1){
memset(ans,0,sizeof(ans));
for(int i=1;i<=50;i++){
len=INF;flag=0;slove(i);
if(flag) ans[i]=len;
}
ll tmp=INF;
for(int i=1;i<=50;i++){
if(ans[i]){
tmp=min(tmp,(ll)ans[i]*i);
}
}
int pos;
for(int i=1;i<=50;i++){
if(ans[i]&&tmp==(ans[i]*i)){
pos=i;break;
}
}
printf("%d %I64d\n",pos,ans[pos]);
}
return 0;
}