您的位置:首页 > 其它

hdu4803 Poor Warehouse Keeper

2015-08-18 16:07 337 查看
给定两个数字显示板A, B和两个按钮,按下按钮使得其对应数字显示增加1。

另,B显示板只显示其实际值的整数部分。两显示器对应的实际值有一个比值p。

按下A板上的按钮, A板上显示的数增加1到a + 1, p不变,B板上的数字更新为(int)(b * (a + 1) / a)。

按下B板上的按钮,A板上上显示的数值不变,B 板加1 到b + 1,p更新为(b + 1) / a。

给定目标状态(a1, b1),问至少经过多少次按下按钮可从初始状态(1, 1)到达该状态。

若不可达输出-1。

显然按下A板按钮使得B板数值成比例增加,比值为p,按下B板数值使得比例增加。

比例增加过程不可逆,状态不可达当且仅当a1 < b1。

首先从A板数组从1增加到a1至少需要a1 - 1次操作,这与B板的状态无关。

而A板的数值变化会引起B板成倍增加,考虑到f(i) = (i + 1) / i是严格递减函数。

直观上我们有应该尽可能把按A板的操作提前,这样B板上的数值就会尽快接近目标值。

注意到比值p<(b + 1) / a,我们尽可能向该值靠近,从1开始。

然后随着A板数值增大,逐步逼近该值,记录下B板的操作次数,即可解决此题。

浮点数执行近似运算,导致误差,本题用分数表示有理数(比值)。

acm.hdu.edu.cn/showproblem.php?pid=4803

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef __int64 LL;

LL a, b;

LL gcd(LL a, LL b){
if(!b) return a;
return gcd(b, a % b);
}

void solve(){
if(b < a){
printf("-1\n");
return;
}
LL lhs = 1, rhs = 1;
//rhs :: denominator
//lhs :: numerator
LL cnt = a - 1;
//operations required for A
for(int i = 1; i <= a; i++){
LL f = (b + 1) * i * lhs - a * rhs, g = a * lhs;
LL k = (f % g == 0 ? f / g - 1 : f / g);
cnt += k;
//extra operations required for B
rhs += k * lhs;
LL GCD = gcd((i + 1) * rhs, i * lhs);
rhs = rhs * (i + 1) / GCD;
lhs = lhs * i /GCD;
}
printf("%I64d\n", cnt);
}

int main(){
while(~scanf("%I64d%I64d", &a, &b)){
solve();
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: