题意:将蛋糕化作R个同心圆插N根蜡烛,同心圆从内到外编号为1~i,第i个圆上需要插K^i根蜡烛,让你找到一组满足组条件且R * K最小的R,K。如果 R1 * K1 = R2 * K2,那么取R较小的那个。同心圆的圆心可以放一根蜡烛或者不放。
思路一(好想但是容易BUG):首先一定存在答案为R = 1,K = n - 1。我们可以发现R不可能太大,于是简单计算一下R不超40。所以我们可以枚举这个R,然后对于这个R二分查找有没有K使满足条件。一定要注意有些地方炸long long!!!。①累加过程中②K^i的下一项。
我由于第二个炸long long的地方,卡了一天,气死。。。
#include<bits/stdc++.h>
using namespace std;
const long long INF = 1e13 + 5;
long long n;
long long check(int r,long long q)
{
unsigned long long sum = 0, an = 1;
for(int i = 1; i <= r; i++)
{
if(n / an < q) return INF;//②炸long long 即 an*k就炸但是an不炸
an = an * q;
sum += an;
if(sum > n) return INF;//①炸long long
}
return sum;
}
int main()
{
while(~scanf("%lld",&n))
{
long long R = 60, K = INF;
for(int i = 1; i <= 40; i++)//枚举R
{
//二分求满足要求的K
long long l = 2, r = n, m = l + (r - l) / 2;
while(l <= r)
{
long long num = check(i,m);
if(num == n || num + 1 == n)//满足要求(圆心摆或者不摆)
{
if(i * m < R * K)
{
R = i; K = m;
}
break;
}
else if(num < n) l = m + 1;
else if(num > n) r = m - 1;
m = l + (r - l) / 2;
}
}
printf("%lld %lld\n", R, K);
}
return 0;
}
思路二(不是很好想):我们注意到这些圆上插的蜡烛个数是一个以K首项以K为公比的等比数列,共有i项,等比数列求和公式为。对于此题那么我们可以得到
或者
两个式子。我们可以枚举R = i 那么正整数K为
或
,维护一下最小的R * K就好了。
K这个值是近似约出来的,也不是很懂为什么一定是这个值,不会有误差吗,谁看出来希望指教一下?
#include<bits/stdc++.h>
using namespace std;
const long long INF = 1e13 + 5;
long long n;
long long check(int r,long long q)
{
long long sum = 0, an = 1;
for(int i = 1; i <= r; i++)
{
an = an * q;
sum += an;
}
return sum;
}
int main()
{
while(~scanf("%lld",&n))
{
long long R = 1, K = n - 1;
for(int i = 2; i <= 40; i++)//枚举R
{
long long k1 = pow(n, 1.0 / i), k2 = (long long)pow(n - 1, 1.0/i);
if(check(i, k1) == n && i * k1 < R * K) R = i, K = k1;
if(check(i, k2) == n - 1 && i * k2 < R * K) R = i, K = k2;
}
printf("%lld %lld\n", R, K);
}
return 0;
}