思路:
分析知道1<=r<40;所以可以枚举r,之后再二分k。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #define ll __int64 9 #define M 2011 10 using namespace std; 11 ll m,rr,kk,mi,n; 12 ll pows(ll a,ll b) 13 { 14 ll ans=1; 15 while(b){ 16 if(b&1) ans=ans*a; 17 b>>=1; 18 a*=a; 19 } 20 return ans; 21 } 22 int fun(ll a,ll r) 23 { 24 ll ans=(pows(a,r+1)-a)/(a-1); 25 if(ans==n||ans==n-1){ 26 if(mi>r*a) return 2; 27 else return 1; 28 } 29 else if(ans>n) return 3; 30 return 0; 31 } 32 int main(){ 33 ll i,j,k,r,le,ri,mid; 34 while(scanf("%I64d",&n)!=EOF){ 35 r=(ll)(log2(n+2)+1)-1; 36 rr=1;kk=n-1;mi=n-1; 37 for(i=2;i<=r;i++){ 38 k=(ll)pow((double)n,1.0/i);//一定满足k^i<n 39 le=2;ri=k; 40 while(le<=ri){ 41 mid=(le+ri)/2; 42 int t=fun(mid,i); 43 if(t==2){ 44 rr=i; 45 kk=mid; 46 } 47 if(t) ri=mid-1; 48 else le=mid+1; 49 } 50 51 } 52 printf("%I64d %I64d ",rr,kk); 53 } 54 return 0; 55 }