第七届蓝桥杯省赛CB-10.最大比例【gcd+辗转相减(更相减损)】

本文探讨了如何通过调查X星球大奖赛的随机奖金数据,推算出可能的最大等比值。利用等比数列性质,通过约分和辗转相减算法求解 gcd,揭示奖金数额间的比例规律。

Date:2022.04.06
题意描述:
X星球的某个大奖赛设了 M 级奖励。
每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。
比如:16,24,36,54,其等比值为:3/2。
现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。
输入格式
第一行为数字 N ,表示接下的一行包含 N 个正整数。
第二行 N 个正整数 Xi,用空格分开,每个整数表示调查到的某人的奖金数额。
输出格式
一个形如 A/B 的分数,要求 A、B 互质,表示可能的最大比例系数。
数据范围
0<N<100
0<Xi<10^12
数据保证一定有解。
输入样例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

思路:随机调查若干个,且等比可能是分数,因此我们将所有项表示为:
a、a∗qx1、......、a∗qxka、a*q^{x_1}、......、a*q^{x_k}aaqx1......aqxk
之后将所有项第一项\frac{所有项}{第一项}约分后,所有项都会转化为等比的若干次幂,形势如下:(pq)k1、(pq)k2、......、(pq)km(\frac{p}{q})^{k_1}、(\frac{p}{q})^{k_2}、......、(\frac{p}{q})^{k_m}(qp)k1(qp)k2......(qp)km
由此不难发现,等比即找k1、k2、......、kmk_1、k_2、......、k_mk1k2......kmgcdgcdgcd即可。
但我们要注意,我们约分后并不知道pq\frac{p}{q}qp的值,因此无法直接对所有幂求gcdgcdgcd,但我们可以预处理出分子和分母,分别求所有分母qk1、qk2、......、qkmq^{k_1}、q^{k_2}、......、q^{k_m}qk1qk2......qkm和分子的gcdgcdgcd再相除。但由于是对幂次求gcdgcdgcd,无法直接辗转相除,因为次幂取模不好处理。因此考虑求gcdgcdgcd的新方法------辗转相减(也就是更相减损术)。
我们要构造的函数无非是:f(px,py)=pgcd(x,y)f(p^x,p^y)=p^{gcd(x,y)}f(px,py)=pgcd(x,y),因此我们反推对次幂更相减损后得到p(x,y)==p(y,y−x),转换为函数形式即为:p^{(x,y)}==p^{(y,y-x)},转换为函数形式即为:p(x,y)==p(y,yx)f(py,pypx)f(p^y,\frac{p^y}{p^x})f(py,pxpy),一路递归,直到后一项次幂为1弹出。
此外,注意更相减损时要用大的减小的,因此我们考虑两个次幂大小,若某一步前面的次幂<后面的次幂,交换位置。而且,题中重复元素要去掉,并不算入这些过程中。
代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
typedef long long LL;
LL n,m,k,t,a[N],b[N],x[N],cnt;
LL gcd(LL a,LL b)
{
    if(!b) return a;
    return gcd(b,a%b);
}
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++) cin>>x[i];
    sort(x+1,x+1+n);
    LL idx=unique(x+1,x+1+n)-x-1;
    for(int i=2;i<=n;i++)
    {
        LL d=gcd(x[i],x[1]);
        a[++cnt]=x[i]/d;
        b[cnt]=x[1]/d;
    }
    LL up=a[1],down=b[1];
    for(int i=2;i<idx;i++)
    {
        up=gcd_sub(up,a[i]);
        down=gcd_sub(down,b[i]);
    }
    cout<<up<<'/'<<down;
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值