2016年蓝桥杯省赛C/C++ A组 最大比例

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/b1, a2/b2, … an/bn},那么需要找到一个最大的p/q,使得数列里面的每个 ai/bi = (p/q)^K,类似最大公倍数。
由于最大数也是10^12,即使底为2,最大幂也只是40,不妨枚举幂的大小,枚举并验证。标程为了避免开方的精度问题,进行了简单的预处理,二分亦可。注意一些细节的处理,精度、溢出等等。

#include <stdio.h>
#include <math.h>
#include <set>
#include <iostream>
using namespace std;

long long gcd(long long x, long long y) {
	return x % y == 0 ? y : gcd(y, x % y);
}
	int a[1001];
	int b[1001];


long long Pow(int x,int n)
{
	long long ans=1;
	for(int i=1;i<=n;i++)
	ans*=x;
	return ans;
}

int test(int aa,int bb,int ai,int bi)
{
	
	for(int i =1;i<=40;i++)
	{
		int pow_a=Pow(aa,i);
		int pow_b=Pow(bb,i);
		if(pow_a==ai && pow_b==bi)
		return 1;
		
		if(pow_a>ai || pow_b>bi)
		break;
	}
	return 0;
}
int main()
{

	int n;
	long long temp,x[1001]={0};
	scanf("%d",&n);
	
	set<long long > set_x;
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&temp);
		set_x.insert(temp);
	}
	
	n=0;
	set<long long>::const_iterator iter_set;//常量迭代器
	for(iter_set=set_x.begin();iter_set!=set_x.end();iter_set++)
	{
		x[n++]=*iter_set;
	}
	
	
	for(int i=0;i<n-1;i++)
	{
		long long gcd_res=gcd(x[i+1],x[i]);
		a[i]=x[i+1]/gcd_res;
		b[i]=x[i]/gcd_res;
	}
	
	
	
	for(int i=1;i<=40;i++)
	{
		float aa=pow(a[0],(double)1/i);
		float bb=pow(b[0],(double)1/i);
		
		if(aa-int(aa)<0.000001  &&  bb-int(bb)<0.000001)
		{
			int flag=0;//找到q的标志 
			for(int j=1;j<n-1;j++) //  对每个a[i]/b[i]   如果aa/bb都满足条件 则符合 
			if(!test(int(aa),int(bb),a[j],b[j]))
			{
				flag=1;//  aa/bb不符合 
				break;
			}
			if(!flag)
			{
				printf("%d/%d\n",int(aa),int(bb));
				break;
			}
			
		}
		
	}
	
	return 0;
}
  1. 利用了set的唯一性和有序性
  2. 对任意的a[i]/b[i] ,满足条件的q 必定存在 a[i]/b[i] =q^n (其中n越小q越大)
  3. 枚举所有可能的q,如何枚举?
    因为a[i]/b[i] =q^n = a^n /b^n 可以发现枚举n就可以了,
    i从1-40,如果a[i]和b[i]开i次方为整数,则是一个可能的Q,然后拿其余的a[i]/b[i]检验Q是否满足Q^j ==a[i]/b[i]
    如果都满足,则输出并退出循环,此时的Q肯定最大,因为a[i]/b[i]是大于1的,一直开根的结果肯定越来越小,所以第一次得出的Q肯定是最大的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值