问题
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
4
3125 32 32 200
3
549755813888 524288 2
输出样例
25/4
5/2
4/1
题解
观察32 200 3125 答案为5/2 可知完整的等比数列为 32, (80), 200, (500), (1250), 3125
可知数列是缺项得到的,但我们将数列排序后,每两个数的比值一定是公比的倍数。例如200/32 = 25/4,可以由 5/2 平方得来,3125/200 = 125/8,可以由 5/2 立方得来。
设一个有n项数列的公比, 则任何项之间的比值一定是
中的一个。 因此给定一些比值后,这些比值必定可以变成公比的k次幂(
)。
由此,我们只需分别求出公比的分子和分母的幂的最大公约数即可。由于我们事先不知每项比值的幂,因此无法通过辗转相除法来做,而求幂的最大公约数可以通过辗转相减法来做。
这里证明一下为什么能用辗转相减法求幂的最大公约数。
首先得证明辗转相除法求最大公约数的原理。
假设有两个数 150 和 60,设它们的最大公约数为x。
显然150和60都能被x整除,
显然90和60都能被x整除,
显然60和30都能被x整除,, 直到最后有一项为0,因此最大公约数为30。
从中我们可以得出一个结论:
其次证明辗转相减法的原理。
设有两个同底的数 , 则
。
完整代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 110;
ll a[maxn], b[maxn], x[maxn];
ll gcd(ll a, ll b)
{
return (!b)?a:gcd(b, a%b);
}
ll gcd_sub(ll a, ll b)
{
if(a < b) swap(a, b);
if(b == 1) return a;
return gcd_sub(b, a/b);
}
int main()
{
int n;
while(cin >> n)
{
for(int i = 1; i <= n; i++) cin >> x[i];
sort(x+1, x+1+n);
int cnt = 0;
for(int i = 2; i <= n; i++)
{
if(x[i] != x[i-1])
{
cnt++;
ll tmp = gcd(x[i], x[i-1]);
a[cnt] = x[i-1] / tmp;
b[cnt] = x[i] / tmp;
}
}
ll son = a[1], parent = b[1];
for(int i = 2; i <= cnt; i++)
{
son = gcd_sub(son, a[i]);
parent = gcd_sub(parent, b[i]);
}
cout << parent << "/" << son << endl;
}
return 0;
}