HDU ~ 4430 ~ Yukari's Birthday(二分or数学)

题意:将蛋糕化作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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值