征战蓝桥 —— 2016年第七届 —— C/C++A组第10题——最大比例

题目

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 , 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

代码

#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>

using namespace std;
typedef long long LL;
int N;
LL data[100];

struct Ratio {
    LL x, y;

    Ratio(LL _x, LL _y) : x(_x), y(_y) {
        LL _gcd = gcd(x, y);
        x /= _gcd;
        y /= _gcd;
    }

    LL gcd(LL a, LL b) {
        if (b == 0)return a;
        return gcd(b, a % b);
    }
};

vector<Ratio> ratios;
map<LL, map<LL,LL> > all_ex;//all_ex[x][pow]==x开pow次方
map<LL, map<LL,LL> > all_log;//all_log[x][y]==log_y_x,y的多少次方是x?
void init(){
    for (int i = 2; i < 1e6; ++i) {//底数
        LL cur=(LL)i*i;
        int pow=2;
        while(cur<1e12){
            all_ex[cur][pow]=i;
            all_log[cur][i]=pow;
            pow++;
            cur*=i;
        }
    }
}
/**
 * 对x开pow次方
 * @param x
 * @param pow
 * @return
 */
LL extract(LL x,LL pow){
    if(pow==1)return x;
    if(x==1)return 1;
    if(all_ex[x].find(pow)!=all_ex[x].end())//意味着x可以开pow整数次方
        return all_ex[x][pow];
    else
        return -1;
}
/**
 * 求log_base_x
 * @param base
 * @param x
 * @return
 */
LL log(LL base,LL x){
    if(base==x)return 1;
    if(all_log[x].find(base)!=all_log[x].end())//意味着可以得打一个k,base的k次方是x
        return all_log[x][base];
    return -1;
}
int main(int argc, const char *argv[]) {
    init();
    freopen("/Users/zhengwei/CLionProjects/lanqiaobei2019/2016_C_A/data10/in8.txt","r",stdin);
//处理输入
    scanf("%d", &N);
    for (int i = 0; i < N; ++i) {
        scanf("%lld", &data[i]);
    }
//排序
    sort(data, data + N);
    //处理只有两项的特殊情况
    if(N==2){
        Ratio ans = Ratio(data[1], data[0]);
        cout << ans.x << "/" << ans.y << endl;
        return 0;
    }
//求两两比值,以分数形式存储,vector
    for (int i = 0; i < N - 1; ++i) {
        if (data[i + 1] != data[i])//去重
            ratios.push_back(Ratio(data[i + 1], data[i]));
    }
//对第一个比值开1~..pow(极限为40).次方,作为基数,如果这个基数也是其他比值的基数的话,该基数就是答案
    for (int pow = 1; pow <= 40; ++pow) {
        Ratio ra0 = ratios[0];
        LL x = ra0.x;
        LL y = ra0.y;
        LL base_x = extract(x, pow);//对x开pow次方,作为基数,去尝试
        LL base_y = extract(y, pow);//对y开pow次方,作为基数,去尝试
        if (base_x == -1 || base_y == -1)continue;//开不出,continue
//        能开:就要去确认所有比值的分子是fx的整数次方,所有比值的分母是fy的整数次方
//计px=getPow(xx,base_x),py=getPow(yy,base_y),要求必须是整数且px==py
        bool all_match = true;
        for (int i = 1; i < ratios.size(); ++i) {
            LL xx = ratios[i].x;
            LL yy = ratios[i].y;
            LL log_x = log(base_x,xx);
            LL log_y = log(base_y,yy);
            if(base_y==1&&yy==1)log_y=log_x;
            if (log_x == -1 || log_y == -1 || log_x != log_y) {
                all_match = false;
                break;
            }
        }
        if (all_match) {
            Ratio ans = Ratio(base_x, base_y);
            cout << ans.x << "/" << ans.y << endl;
            return 0;
        }

    }
    return 0;
}
posted @ 2019-03-15 21:36  AlexKing007  阅读(70)  评论(0编辑  收藏  举报