AcWing 1223. 最大比例
原题链接
思路
首先肯定和等差数列类似,先把所输入的项排序去重,然后两两相邻项进行整除,可以得到许多的商(全部都是最大公比的若干倍)
然后也和等差数列类似,要想办法求出在乘方后能够得到所有得到的商的最大数,等差数列将所有的差求gcd就行,那么等比数列却不行,怎么办?
假设所求最大公比是\(p/q\), 注意到所有得到的商都是 \(p^x / q^x\), 因此,只需要把它们的指数求gcd即可。
但是\(p/q\)是未知的,因此也无从确定所得商的指数,怎么办?巧妙就在这里!
又注意到指数不会太大,而且指数的减法可以表示为原来的数的除法,因此用gcd_sub(更相减损术)即可解决!
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 110;
typedef long long ll;
ll x[N], a[N], b[N];
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);
int len = unique(x, x + n) - x; //排序并去除重复的项
for(int i = 1 ; i < len ; i ++) //求出相邻两项的商 其中a代表分子,b代表分母
{
ll d = gcd(x[i], x[i - 1]);
a[i - 1] = x[i] / d;
b[i - 1] = x[i - 1] / d;
}
ll up = a[0], down = b[0]; //对所有的商的质数求最大公约数
for(int i = 1 ; i < len - 1 ; i ++)
{
up = gcd_sub(up, a[i]);
down = gcd_sub(down, b[i]);
}
cout << up << "/" << down << endl;
return 0;
}