2016蓝桥杯C++A组——最大比例

该博客讨论了一个算法问题,涉及寻找一组整数中,能够使得所有比值都为同一分数的不同次方的基数。首先对输入整数排序并去重,然后计算两两相邻数的比值并存储为分数形式。接着对第一个比值开平方根,检查是否能作为其他比值的基数。通过预处理快速幂和对数运算,找到满足条件的基数并输出答案。
摘要由CSDN通过智能技术生成

最大比例题目链接

问题描述

【题目描述】
在这里插入图片描述
【输入】
在这里插入图片描述
【输出】
在这里插入图片描述
【样例输入】

3
1250 200 32
4
3125 32 32 200
3
549755813888 524288 2

【样例输出】

25/4
5/2
4/1

题目解析

  1. 首先处理输入,对所有输入的整数排序加去重。
  2. 对两两相邻数求比值并用分数形式存储,可以存储到vector中。
  3. 对第一个比值开1~k次方,作为基数,如果该基数同样也是其他比值的基数的话,那么这个基数就是答案。

C++代码

#include<bits/stdc++.h>
using namespace std;
int N;
typedef long long LL;
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 x,LL y)
    {
        if(y==0) return x;
        return gcd(y,x%y);
    }
};
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]表示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;
        }
    }
}
LL extract(LL x,LL pow) //对x开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;
}
LL log(LL base,LL x) //求log(base_x)
{
    if(base==x) return 1;
    if(all_log[x].find(base)!=all_log[x].end())
        return all_log[x][base];
    else return -1;
}
int main()
{
    init();
    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;
    }
    for(int j=0;j<N-1;j++) //求两两比值并以分数形式存储进vector中
    {
        if(data[j+1]!=data[j]) //去重
            ratios.push_back(Ratio(data[j+1],data[j]));
    }
    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的整数次方
        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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芷汀若静

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值