最大比例

这篇博客探讨了如何寻找一个有序序列中两两元素比值的最大公比。首先对序列进行排序和去重,然后计算相邻元素的比值,并通过求最大公约数的方法找到使得所有比值为某一次方的公比。文章介绍了相减法来求最大公约数,最终通过代码展示了如何实现这一算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析:为了保证所得的公比最大,首先要对原序列进行排序和去重,这个我就不细说了,我主要来说一下公比应该怎样求:

假设我们排完序的序列为a1,a2,……,an

那么我们可以对应的求出两两之间的比值为qi/pi,现在我们就是要求得p和q使得对于任意的两两相邻数的比值qi/pi为q/p的若干次方,而且为了使q/p尽量大,所以我们要保证若干次方尽可能小,那显然结果就是所有指数的最大公约数为1了,而且题目中保证有解,所以我们可以单独求分子和分母,最后算的次方肯定是一一对应的,现在的问题就转化为了如何求得p^x1,p^x2,……p^xn的最大满足p^x形式的公约数,其实写到这我们也不难发现,只需要求x1,x2,……xn之间的最大公约数即可得到x,但问题是xi在指数上,没法直接用求最大公约数的方法来进行求解,下面就需要介绍相减法来求得最大公约数。

先来看一下原始求得最大公约数的方法,若x>y>0,就返回gcd(y,x%y),但是我们知道其实也可以返回gcd(y,x-y),只是这样进行比较慢而已,而这道题由于x在指数上,所以只能采取这种方法,我们可以利用两数相除来得到指数相减的目的,这样我们就可以求得满足要求形式的最大公约数,下面是相减法求最大公约数的代码:

ll gcd_sub(ll x,ll y)
{
	if(x<y) return gcd_sub(y,x);
	if(y==1) return x;
	return gcd_sub(y,x/y);
}

但是需要注意,相减法求最大公约数时本质上是用两数相除递归到下一次调用函数,所以终止条件应该是有一个数等于1.

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
const int N=103;
typedef long long ll;
ll a[N],p[N],q[N];
ll gcd(ll x,ll y)
{
	if(y==0) return x;
	return gcd(y,x%y);
}
ll gcd_sub(ll x,ll y)
{
	if(x<y) return gcd_sub(y,x);
	if(y==1) return x;
	return gcd_sub(y,x/y);
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	sort(a+1,a+n+1);
	int cnt=0;
	for(int i=2;i<=n;i++)
	{
		if(a[i]==a[i-1]) continue;
		else
		{
			ll t=gcd(a[i-1],a[i]);
			p[++cnt]=a[i-1]/t;
			q[cnt]=a[i]/t;
		}
	}
	ll ansp=p[1],ansq=q[1];
	for(int i=2;i<=cnt;i++)
	{
		ansp=gcd_sub(ansp,p[i]);
		ansq=gcd_sub(ansq,q[i]);
	}
	printf("%lld/%lld\n",ansq,ansp);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值