蓝桥杯 最大比例

2016年第七届蓝桥杯C/C++程序设计本科B组省赛题目汇总:

http://blog.csdn.net/u014552756/article/details/50946357


最大比例

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

并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。比如:
16,24,36,54
其等比值为:3/2

现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。

输入格式:
第一行为数字N(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

资源约定:
峰值内存消耗 < 256M
CPU消耗  < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。


思路:我们先把问题特殊化,假设只有三个数a1,a2,a3从小到大排列,其中a2 = a1 * (up/down)^i , a3 = a1 * (up/down)^(i+j),设公比q =(up/down) 。 p1= a2/a1 = (up/down)^i,p2=a3/a2 = (up/down)^j,假设公比为qq = (up/down)^k。则k为i和j的最大公因数.这里在进行特殊化,假设p2>p1.则p2/p1 = (up/down)^(j-i)。此时p2/p1是完全可以由输入算出的j和i为我们的假设,当j-i越大,我们的p越小,可见,当j-i为1时p = (up/down)最大,此时便可以把p2/p1当结果输出。

再回到一般情况的处理:

首先把输入的数按从小到达排列,再算他们的相邻两个数的比例,保存起来,如果两个数相同的话就跳过不算。此时保存下来的的数据就是上面特殊化的p1,p2这些数据,但是这个时候不能保证p1,p2.....递增,所以进行从小到大排列,此时值需算出其中p(i+1)/pi,取里面最小的数min,然后把min输出就是最终的结果。

整个思路就是这样,另外这里要设计到约分,还要定义一个结构体来存放分数。以下是代码,试了题目的几组数据都可以输出正确。

#include
#include
#include
#include
using namespace std;

#define ll long long



int n;
ll x[100];
int pos = 0;
Data min1;

struct Data
{
	long long int up;
	long long int down;
}d[100];



//test
void show1()
{
	int i;
	for(i = 0;i < pos;i++)
	{
		cout << d[i].up << " " << d[i].down << endl;
	}
}


bool cmp(Data &a,Data &b)
{
	return a.down < b.down;
}


int gcd(ll a,ll b)
{
	ll t;
	while(b)
	{
		t = b;
		b = a % b;
		a = t;
	}
	return a;
}
//求出pi,即从小到大排列,相邻两个输入数据之间的倍数
void make_data()
{
	int g;
	int i;
	for(i = 0;i < n-1;i++)
	{
		if(x[i] == x[i+1])
		{
			continue;
		}
		g = gcd(x[i],x[i+1]);
		d[pos].up = x[i+1] / g;
		d[pos].down = x[i] / g;
		pos++;
	}
//	show1();
}
//对排序后的pi进行两两相除,算出除出来的最小的数。
void deal_data()
{
	int i;
	int t1,t2;
	sort(d,d+pos,cmp);
	
	min1.down = d[0].down;
	min1.up = d[0].up;
	for(i = 0;i < pos - 1;i++)
	{
		int g1;
		int g2;
		g1 = gcd(d[i].up,d[i+1].up);
		g2 = gcd(d[i].down,d[i+1].down);
		t1 = (d[i].up / g1) * (d[i+1].down / g2);
		t2 = (d[i].down / g2) * (d[i+1].up / g1) ;
		if(t1 == 1 && t2 == 1)
		{
			continue;
		}
		if(min1.up > t2 || min1.down > t1)//有可能分子为1
		{
			min1.down = t1;
			min1.up = t2 ;
		}
	}
}


int main() 
{
	cin >> n;
	int i;
	for(i = 0;i < n;i ++)
	{
		cin >> x[i];
	}
	sort(x,x+n);
	make_data();
	deal_data();
	cout << min1.up << '/' << min1.down;
	/*
	long long int a = 18,b = 12;
	cout << gcd(a,b);*/
}

你可能感兴趣的:(蓝桥杯)