[第七届蓝桥杯省赛C++ A组/B组]最大比例详解(数学)

题目

X星球的某个大奖赛设了 M M M 级奖励。

每个级别的奖金是一个正整数。

并且,相邻的两个级别间的比例是个固定值。

也就是说:所有级别的奖金数构成了一个等比数列。

比如: 16 , 24 , 36 , 54 16,24,36,54 16,24,36,54,其等比值为: 3 / 2 3/2 3/2

现在,我们随机调查了一些获奖者的奖金数。

请你据此推算可能的最大的等比值。

输入格式

第一行为数字 N N N ,表示接下的一行包含 N N N 个正整数。

第二行 N N N 个正整数 X i X_i Xi,用空格分开,每个整数表示调查到的某人的奖金数额。

输出格式

一个形如 A / B A/B A/B 的分数,要求 A 、 B A、B AB 互质,表示可能的最大比例系数。

数据范围

0 < N < 100 0 < N < 100 0<N<100
0 < X i < 1 0 12 0 < X_i < 10^{12} 0<Xi<1012
数据保证一定有解。

输入样例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

思路:

  1. 取到相邻两个数的比例,放入set()中;
  2. 取得分子,分母的最大公约数(如 样例2中 25/4 , 125/8 得到 a=25 ,b = 4)
  3. 因为答案肯定是原比例的约数,又肯定比2中要小(分子<分子;分母<分母),所以答案藏在其中,枚举约数,又因为答案的分子^n /分母 ^n 构成了 1 中得到的比例,所以我们求2 中得到a,b 的满足pow(minia,n) ==a的最小约数。(比如说a = 8 ,那么我们得到2,因为2^ 3 ==8;a = 12,我们得到12就可以了,因为只有12^1 ==12满足条件)

(附上自己的丑代码)

import math
n = int(input())

h = list(map(int,input().split()))

k = set()
def gcd(a,b):
    if b==0:return a
    return gcd(b,a%b)
h.sort()
for i in range(1,n):
    t = gcd(h[i],h[i-1])
    a = h[i]//(t)
    b = h[i-1]//t
    if a == b :continue
    k.add((a,b))
#print(k)
k = list(k)
a , b =k[0][0],k[0][1]
for x,y in k[1:]:
    a = gcd(a,x)
    b = gcd(b,y)
#print(a,b)

def findMiniPrime(n):
    if n ==1:return 1
    i = 2; t =int(n**0.5);nn = n;f=False
    while i<=t and n!=1:
        if (nn%i == 0 and math.log(nn)/math.log(i)-int(math.log(nn)/math.log(i)) <1e-5):
            f=True
            break
        i+=1
    if f:return i
    return nn

a = findMiniPrime(a)
b = findMiniPrime(b)

minia = a
minib = b
cnt = 1

#print(math.log(k[0][0])/math.log(a)-math.log(k[0][0])//math.log(a) == 0)
def judge(x,a):
    if a == 1:return False
    return (math.log(x)/math.log(a)-int(math.log(x)/math.log(a)))<1e-5 
f = [True,True]
while True:
    for x in k:
        #print(x,a,math.log(x[0])/math.log(a),int(math.log(x[0])/math.log(a)),judge(x[0],a))
        if (not judge(x[0],a)) or a>x[0] :
            f[0] = False
            break
    if f[0]:
        a*=minia
    else:break
while True:
    for x in k:
        if (not judge(x[1],b)) or b>x[1] :
            f[1] = False
            break
    if f[1]:
        b*=minib
    else:break
#print(a,' ',b)
print(a//minia,"/", b//minib,sep = '')
#print(k,minia,minib)

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值