这道题是长春赛区的K题;
题意:(K^r)+(K^(r-1))+....+K+1=N,或:(K^r)+(K^(r-1))+....+K=N;给出N,求K和R的值,如果有多个答案,输出R*K最小的那个;k>=2;N<=10^12;
题解:R一定是小于40的(K大于等于2),枚举R的值,R的值一定的情况下,N相对于K是单调递增的,故用二分求答案
#include <iostream>
#include <cstring>
#include <cstdio>
#include <fstream>
using namespace std ;
long long n , r , k ;
long long find( long long left , long long right , long long num )
{
int i , j ;
long long mid ;
long long sum ;
long long tmp ;
while( left <= right )
{
int flag = 0 ;
mid = ( left + right ) / 2 ;
sum = 0 ; tmp = 1 ;
for( i = 1 ; i <= num ; i ++ )
{
if( sum > n / mid )
{
right = mid - 1 ;
flag = 1 ;
break ;
}
tmp *= mid ;
sum += tmp ;
}
if( flag ) continue ;
if( sum == n ) return mid ;
if( sum > n ) right = mid - 1 ;
if( sum < n ) left = mid + 1 ;
}
return 0 ;
}
int main()
{
int i , j ;
while( scanf( "%lld" , & n ) != EOF )
{
k = n - 1 ;
r = 1 ;
for( i = 2 ; i <= 40 ; i ++ )
{
long long t = find( 2 , n , i ) ;
if( t == 0 ) continue ;
if( i * t < r * k || ( i * t == r * k && i < r ) )
{
r = i ;
k = t ;
}
}
n -- ;
for( i = 2 ; i <= 40 ; i ++ )
{
long long t = find( 2 , n , i ) ;
if( t == 0 ) continue ;
if( i * t < r * k || ( i * t == r * k && i < r ) )
{
r = i ;
k = t ;
}
}
printf( "%lld %lld\n" , r , k ) ;
}
return 0 ;
}