蓝桥杯 最大比例

题目描述 

最大比例

X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。

并且,相邻的两个级别间的比例是个固定值。

也就是说:所有级别的奖金数构成了一个等比数列。比如:

16,24,36,54

其等比值为:3/2

现在,我们随机调查了一些获奖者的奖金数。

请你据此推算可能的最大的等比值。

输入格式:

第一行为数字 N (0<N<100),表示接下的一行包含N个正整数

第二行N个正整数Xi(Xi<1 000 000 000 000),用空格分开。每个整数表示调查到的某人的奖金数额

要求输出:

一个形如A/B的分数,要求A、B互质。表示可能的最大比例系数

测试数据保证了输入格式正确,并且最大比例是存在的。

例如,输入:

3

1250 200 32

程序应该输出:

25/4

再例如,输入:

4

3125 32 32 200

程序应该输出:

5/2

再例如,输入:

3

549755813888 524288 2

程序应该输出:

4/1 

思路:

这道题目的是想求等比数列的这个公比最大是多少,既然要求公比的话直接将这个数列任意两个数相除必定是公比的k次方。

所以第一步需要将所有的数都互相除一遍,把所有的公比的k次方求出来,然后再找最小的。怎么找最小的?这个道理很简单,公比是需要所有数都可以整除它,你如果不找最小的那么有些数肯定是整除不了的。但是找到这些整除后的数最小的后还是不一定可以确定公比就是它。 

看到这里可能会有点思路但是还是云里雾里,那么举个列子吧。

题目中输入数据:3125 32 32 200

  1. 将所有数互相整除,获得整除后的结果集合。

3125除32=3125/32
3125除200=125/8
32除32=1/1
32除200=25/4

当然1/1这个不算,整除后数列最小是25/4.那么最终的公比是25/4了吗?当然不是。

等比数列公式Ai=kq^i;所以Ai/Aj=(q^i)/(q^j);而(q^i)/(q^j)=q^m。所以25/4目前只能算是q^m,我们要求公比q。

q可以看做q^1,所以在整除后数列中应该所有数都是公比q的整数次方。

上面这句话用程序怎么表示?下面是伪代码:意思就是x可以一直除公比q直到x=1。如果最后得到x不是1那么证明x不是q的整数次方。比如:9和27的关系,9显然不是27的公比,因为27/9=3,最后的结果不是1。而3和9,9/3/3=1所以3是9的公比。

我们假设的公比25/4不是公比那么怎么求呢?上面这段话给了提示,27/9=3.  9不是公比但是3是啊。所以若最后x不等于1那么x就是公比,我们要更新假设的公比。

int x=25/4;

while(x>q){

   x=x/q;

}

if(x==1)

print("x是q的整数次方");

具体代码


import java.math.BigInteger;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
//用于保存一个分数避免出现除不断情况
class fenshu {
	public BigInteger top;
	public BigInteger below;

	fenshu() {
	}

	fenshu(BigInteger top, BigInteger below) {
		this.top = top;
		this.below = below;
	}
}

public class XMax {
//求最大公约数
	public static BigInteger f(BigInteger a, BigInteger b) {
		if (a.signum() == 0)
			return b;
		return f(b.mod(a), a);
	}
//假设的公比的分子
	public static BigInteger mintop = new BigInteger("1000000000000");
//假设公比的分母
	public static BigInteger minbelow = new BigInteger("1000000000000");
//最小的分子
	public static BigInteger tempmintop;
//保存奖金数值
	public static BigInteger[] digit;
	public static int n;
	public static BigInteger temp;
//保存整除后的数列
	public static Set<fenshu> set = new LinkedHashSet<>();

	public static void fmin(int step) {
		if (step >= n)
			return;
		for (int i = step + 1; i < n; i++) {
			temp = f(digit[step], digit[i]);
			boolean flag = true;
			fenshu t = new fenshu();
			if (digit[step].compareTo(digit[i]) > 0) {
				t.top = tempmintop = digit[step].divide(temp);
				t.below = digit[i].divide(temp);
			} else {
				t.top = tempmintop = digit[i].divide(temp);
				t.below = digit[step].divide(temp);
				flag = false;
			}
			set.add(t);
			if (!tempmintop.equals(BigInteger.ONE)
					&& tempmintop.compareTo(mintop) < 0) {
				mintop = tempmintop;
				if (flag)
					minbelow = digit[i].divide(temp);
				else
					minbelow = digit[step].divide(temp);
			}
		}
		fmin(step + 1);
	}

	public static void main(String[] args) {
		digit = new BigInteger[] { new BigInteger("549755813888"),
				new BigInteger("524288"), new BigInteger("2") };
		n = digit.length;
		fmin(0);//计算出不同两位数相除得到的商,这些商可能存在公比
		Iterator iter = set.iterator();
		fenshu t = new fenshu();
		while (iter.hasNext()) {
			t = (fenshu) iter.next();
			while (t.top.compareTo(mintop) > 0) {
				t.top = t.top.divide(mintop);
				t.below = t.below.divide(minbelow);
			}
//如果等于1证明能整除,如果不等于1证明mintop/minbelow还不够小,目前的t.top/t.below更小更适合。
			if (!t.top.equals(BigInteger.ONE)) {
				mintop = t.top;
				minbelow = t.below;
			}
		}
		System.out.println(mintop + "/" + minbelow);
	}
}

 

转载于:https://my.oschina.net/yuanmuou/blog/873291

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值