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
程序应该输出:
25/4
再例如,输入:
4
3125 32 32 200
程序应该输出:
5/2
再例如,输入:
3
549755813888 524288 2
程序应该输出:
4/1
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
由题目分析可知,给定的n个数为某一等比数列中的若干项(这些抽出来的若干项可连续、可不连续,且可以相同);其次由等比数列的递推公式an=a1*q^(n-1)可知,这n个数均可以表示为a1*q^k(k为任意非负整数);我们需要求的是可能的最大的公比Q
由等比数列的通式,a1是无关项,则且将n个数前后两两相除并升序排序,得到的n-1项为:q^m q^n q^s q^t q^u ... q^z(这n-1项的每一项直观的理解就是相邻的两个数相差原公比q的多少次方,即中间隔几项),可见,我们只需求出这些项的指数的最大公约数g即可(此时最大公比Q即为q^g);但是这些项可能是分数,给我们带来很大的困难
此路不通,那我们就换种方法求最大公比:让这些q的k次幂项不断地前后两两相除!最终得到的即为最大的公比Q
思路是参考别人的,且看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#define MAXN 1000000000000
typedef long long ll;
using namespace std;
ll gcd(ll a, ll b) {// 求最大公约数(参数为整数)
while (b != 0) {
ll tmp = a;
a = b;
b = tmp % b;
}
return a;
}
ll arr[105];// 原数据
struct F {// 定义一个最简分数的结构体
ll up, dw;// up为分子、dw为分母
F() {}
F(ll a, ll b) {
if (a == 0) {// 注意特殊情况的处理
up = 0, dw = 1;
return;
}
ll g = gcd(a, b);
up = a / g, dw = b / g;
}
bool operator <(const F &t) const {// 1、比大小 2、sort
return (up*t.dw < dw*t.up);
}
bool operator ==(const F &t) const {
return (up*t.dw == dw*t.up);
}
F operator /(const F &t) const {
return F(up*t.dw, dw*t.up);
}
void print() {
printf("%I64d/%I64d\n", up, dw);
}
}f[105];
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
//scanf("%I64d", arr[i]);
cin>>arr[i];
}
sort(arr, arr+n);// 排序
n = unique(arr, arr+n) - arr - 1;// 去重(得到的n为前后两两相除之后的总个数,所以要在原来的基础上减1,下同)
for (int i = 0; i < n; i++) {// 前后两两相除
f[i] = F(arr[i+1], arr[i]);
}
F ans(MAXN, 1);
while (n > 1) {// 剩余的个数为1时才结束循环
sort(f, f+n);// 排序
n = unique(f, f+n) - f - 1;// 去重
if (f[0] < ans) {
ans = f[0];
}
for (int i = 0; i < n; i++) {// 前后两两相除
f[i] = f[i+1] / f[i];
}
}
if (f[0] < ans) {
ans = f[0];
}
ans.print();
return 0;
}