【蓝桥杯】【比酒量】

题目

有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复...... 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船......” 
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。 
如果有多个可能的答案,请列出所有答案,每个答案占一行。 
格式是:人数,人数,... 
例如,有一种可能是:20,5,4,2,0。

 

分析

根据题目描述,船长每次都参与了喝酒,并且船长喝了4次总共喝了1瓶酒;

可以分析出题目的需求是要找到4个分数之和等于1,并且这4个分数的分子都是1,需要我们通过编程找到分母。

 

源码

我们需要一个有理数类,这个类包括一个分子和一个分母两个属性,代码如下:

 

public class Rational {

	private int fz; // 分子
	private int fm; // 分母

	public Rational(int fz, int fm) {
		int gcd = gcd(fz, fm); // 获取到fz和fm的最大公约数
		this.fz = fz / gcd; // 对分子进行约分
		this.fm = fm / gcd; // 对分母进行约分
	}

	// 当前分数与其他分数进行加法运算
	// 原理:a/b + c/d = (ad+bc)/bd
	public Rational add(Rational n) {
		Rational ret = new Rational(
				(this.fz * n.getFm() + this.fm * n.getFz()), this.fm
						* n.getFm());
		return ret;
	}

	public int getFz() {
		return fz;
	}

	public void setFz(int fz) {
		this.fz = fz;
	}

	public int getFm() {
		return fm;
	}

	public void setFm(int fm) {
		this.fm = fm;
	}

	/**
	 * 利用辗转相除法计算两个数x和y的最大公约数
	 * 
	 * @param x
	 * @param y
	 * @return 返回x和y的最大公约数
	 */
	private int gcd(int x, int y) {
		if (y == 0) {
			return x;
		} else {
			return gcd(y, x % y);
		}
	}

}


接下来我们就可以开始通过4层for循环来遍历搜寻我们需要找到的答案,代码如下:

 

 

public class Test001 {

	public static void main(String[] args) {

		for (int i = 20; i > 0; i--) {
			for (int j = i - 1; j > 0; j--) {
				for (int p = j - 1; p > 0; p--) {
					for (int q = p - 1; q > 0; q--) {
						Rational a = new Rational(1, i);
						Rational b = new Rational(1, j);
						Rational c = new Rational(1, p);
						Rational d = new Rational(1, q);
						Rational ret = a.add(b).add(c).add(d);
						if (ret.getFz() == 1 && ret.getFm() == 1) {
							// 找到了一组答案
							System.out.println(i + "," + j + "," + p + "," + q
									+ ",0");
						}
					}
				}
			}
		}
	}
}

 

 

结果

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值