题面
X 星球的某个大奖赛设了 M 级奖励。每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。比如:16,24,36,54,其等比值为:
现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。
输入描述
第一行为数字 ,表示接下的一行包含 N 个正整数
第二行 N 个正整数 ,用空格分开。每个整数表示调查到的某人的奖金数额
输出描述
一个形如 A/B 的分数,要求 A、B 互质。表示可能的最大比例系数。
测试数据 保证了输入格式正确,并且最大比例是存在的。
输入样例 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
题解
最大公因数,数论
先将读入的数组进行排序去重,再进行处理。
记 nums[0]
为首项,则当 ,有 下式子:
其中 为 最小公比, 为严格单调递增的整数。
题目要求 最大公比, 则可以转化为找到一个最大的 , 使得 ( 为整数)成立,则可以知道,我们的目标即为找到满足 的 , 而 表示为分数形式(),则同理只要求出分子 的 ,即为分母的 。
计算出每一个数 nums[i]
()与第一个数 nums[0]
的最简比例,记为 a[i]/b[i]
,有 ,再对分子 a
数组进行上述的求 即可。
而对于一个 这样的序列,要求其中 的最大公因数,则需用到 辗转相减法 的变形形式。
对于常规的求两个数 a 和 b 的最大公因数 ,辗转相减法伪代码如下:
def gcd(a, b):
if a < b: swap(a, b)
if a == b: return a
return gcd(b, a - b)
如求 12 和 15 的最大公因数如下计算:
则在本题中,我们求 和 的幂的最大公因数,则将两数相除,就能实现减法,即 ,这样即可求的答案 ,其伪代码如下:
# 传入的参数为 a(q^k1) 和 b(q^k2),返回 q^gcd(k1, k2)
def gcd_sub(a, b):
if a < b: swap(a, b)
if a == b: return a
return gcd(b, a / b)
具体实现过程见代码。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 105;
int n;
LL a[N], b[N];
vector<LL> nums;
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
//辗转相减法,变形---
// 对 a 和 b 的表示法 x^i 和 x^j 的幂 i j 进行取最大公因数,返回 x^gcd(i, j)
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() {
cin >> n;
for (int i = 1; i <= n; i++) {
LL x;
cin >> x;
nums.push_back(x);
}
//排序并去重
sort(nums.begin(), nums.end());
nums.erase(unique(nums.begin(), nums.end()), nums.end());
n = nums.size();
for (int i = 1; i < n; i++) {
LL g = gcd(nums[i], nums[0]);
a[i] = nums[i] / g;
b[i] = nums[0] / g;
}
LL fz = a[1], fm = b[1];
for (int i = 2; i < n; i++) {
fz = gcd_sub(a[i], fz);
fm = gcd_sub(b[i], fm);
}
printf("%lld/%lld\n", fz, fm);
return 0;
}
标题: | 2016年第七届蓝桥杯省赛-J. 最大比例 |
---|---|
链接: | https://www.fightingok.cn/detail/188 |
更新: | 2022-09-18 22:46:40 |
版权: | 本文采用 CC BY-NC-SA 3.0 CN 协议进行许可 |