X星球的某个大奖赛设了 M 级奖励。
每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。
比如:16,24,36,54,其等比值为:3/2。
现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。
输入格式
第一行为数字 N ,表示接下的一行包含 N 个正整数。
第二行 N 个正整数 Xi,用空格分开,每个整数表示调查到的某人的奖金数额。
输出格式
一个形如 A/B 的分数,要求 A、B 互质,表示可能的最大比例系数。
数据范围
0<N<100
0<Xi<1012
数据保证一定有解。
输入样例1:
3
1250 200 32
输出样例1:
25/4
输入样例2:
4
3125 32 32 200
输出样例2:
5/2
输入样例3:
3
549755813888 524288 2
输出样例3:
4/1
假设原数列为 a,a*(p/q)^1, a*(p/q)^2,…, a*(p/q)^(n-1)
假设抽取的数列 b0,b1,…,b(N-1) (从小到大排好序了)
b1/b0,b2/b0,…,b(N-1)/b0–> (p/q)^x1, (p/q)^x2,…, (p/q)^x(N-1)
我们要求的是: (p/q)^k (p/q)>1,所以使k最大,即求(p/q)^x1~ (p/q)^x(N-1)的最大公约数,其实就是求x1~x(N-1)的最大公约数
//这里我们使用更相减损术,因为我们没有得到确切的x1~x(N-1)是多少,我们只有(p/q)^x1, (p/q)^x2,…, (p/q)^x(N-1)这些的值
更相减损术:第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
则第一步中约掉的若干个2的积与第二步中等数的乘积就是所求的最大公约数。
更相减损术总用较大的减去较小的
例子:
98-63=35
63-35=28
35-28=7
28-7=21
21-7=14
14-7=7
所以,98和63的最大公约数等于7。
我们这里要用更相减损术的是指数,所以要让(p/q)^x1 ,(p/q)^x2,…, (p/q)^x(N-1),两两计算,互除,除到结果为1,即x1=x2,此时幂次为0,结果为1。
把分子分母分别去算,结果是相同的因为,分子分母的幂次是相同的
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 110;
typedef long long ll;
ll x[N], a[N], b[N];
int cnt = 0;
ll gcd(ll a, ll b)
{
return b ? gcd(b, a % b) : a;
}
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;
cin >> n;
for(int i = 0; i < n; i ++) cin >> x[i];
sort(x, x + n);
for(int i = 1; i < n; i ++)
{
if(x[i] != x[i - 1])
{
ll d = gcd(x[i], x[0]);
a[cnt] = x[i] / d;//分子
b[cnt] = x[0] / d;//分母
cnt ++;
}
}
ll up = a[0], down = b[0];
for(int i = 1; i < cnt; i ++)
{
up = gcd_sub(up, a[i]);//求最大公约数
down = gcd_sub(down, b[i]);
}
cout << up << "/" << down << endl;
return 0;
}