题目来源:第七届蓝桥杯省赛c++ b组 第十题
最大比例
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
解题思路
先sort排序并去重
然后计算两两之间的奖金比例
最后计算奖金比例的最小公比
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f;
class FS{//分数
public:
ll fz;
ll fm;
public:
FS(ll fz_=1,ll fm_=1){
fz=fz_;
fm=fm_;
yf();
}
void set(ll fz_,ll fm_){
fz=fz_;
fm=fm_;
yf();
}
void set(FS x){
fz=x.fz;
fm=x.fm;
yf();
}
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
void yf(){//约分
ll g=gcd(fz,fm);
fz/=g;
fm/=g;
}
friend ostream & operator<<(ostream &out, FS &x);
friend bool operator<(FS &x,FS &y);
};
bool operator<(FS &x,FS &y){
if(1.0*x.fz/x.fm < 1.0*y.fz/y.fm)
return true;
else return false;
}
ostream & operator<<(ostream &out, FS &x){
cout<<x.fz<<'/'<<x.fm;
return out;
}
bool cmp(FS a,FS b){
return a<b;
}
const int N=105;
int n;
ll a[N];
FS b[N];//存比例
void printArray(ll *a,int n){
for(int i=0;i<n;i++)
cout<<a[i]<<"\t";
cout<<endl;
}
void printArray(FS *a,int n){
for(int i=0;i<n;i++)
cout<<a[i]<<"\t";
cout<<endl;
}
void solve(){
//PART1
//对奖金排序
sort(a,a+n);
//去掉重复的数字
int k=1;
for(int i=1; i<n; i++){
if(a[i]!=a[i-1])
a[k++]=a[i];
}//得到k的不重复数字的升序
printArray(a,k);
//PART2
//生成奖金比例
for(int i=1;i<k;i++){
b[i-1].set(a[i],a[i-1]);
}
//PART3
//对奖金比例排序
sort(b,b+k-1,cmp);
//去掉重复的数字
int k2=1;
for(int i=1;i<k-1; i++){
if(b[i]<b[i-1]||b[i-1]<b[i])
b[k2++].set(b[i]);
}//得到k的不重复数字的升序
printArray(b,k2);
//PART4
//找到最小公比
FS minb(INF,1);
for(int i=1;i<k2;i++){
FS x(b[i].fz*b[i-1].fm,b[i-1].fz*b[i].fm);//b[i]/b[i-1]
if(x<minb)
minb=x;
}
cout<<minb<<endl;
}
int main(){
while(~scanf("%d",&n)){
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
solve();
}
return 0;
}