PAT(Python)-1030:完美数列(25)

来源:互联网 发布:淘宝老客户刷销量 编辑:程序博客网 时间:2024/06/10 06:49

给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。

现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式:

输入第一行给出两个正整数N和p,其中N(<= 105)是输入的正整数的个数,p(<= 109)是给定的参数。第二行给出N个正整数,每个数不超过109

输出格式:

在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

——————————————————————————————————

刚开始看到这道题的N和p都那么大,于是第一时间想到的是:

(1)不能直接用循环来求完美数列最大长度;

(2)输入数列肯定要先进行排序。

因此,不(mei)假(zhang)思(nao)索(zi)地想:

A:找到最小值m的index,升序数列中<= m*p的最大项对应的index,然后index之差加1就是此时的完美数列的长度了。

B:最小值m从第一项开始逐渐往后取,但要循环到哪一项就停止呢?我们用数列最大值M可以反过来找到满足M <= m * p的m的最小值对应在有序列表中的index就是循环次数,由此出现了效率低,特殊情况多,容易出错的代码,见本文所附问题代码。。。

提交答案发现,测试点2答案错误,测试点4超时,这个时候我就觉得不对了,参考了一下网上别人的想法,发现我真是太愚蠢了,具体如下:

—————————————————————————————————

A:对最小值的选取从有序列表第一项开始循环;

B:在上述循环内对最大值的选取进行循环,保存此时的完美数列项数;

C:既然我们是为了获取完美数列项数最大值,那就注意,最大值所在内层循环可以优化:从最小值index加上完美数列项数形成下一次内层循环的最小index。

具体正确代码实现如下,由此可见本题的关键在于步骤C

N,q = map(int, input().split())  # 获取数列长度N,完美数列所需比值qli = list(map(float, input().split()))  # 获取数列li.sort()  # 对数列排序m = 0  # 符合条件的完美数列长度,初始化为0for i in range(N):  # 完美数列最小项循环    m_q = li[i] * q  # 完美数列最小项*q</span>    next_ = i+m  # 完美数列最大项+1,作为内层完美数列最大项循环的下界    if next_ >= N:  # 判断是否已达到数列末项        break    for j in range(next_,N):  # 完美数列最大项循环</span>        if li[j] <= m_q:  # 第j项满足完美数列条件,则完美数列长度+1            m += 1        else:  # 最大值项达不到条件,推出循环            breakprint(m)


问题代码如下:

def find_i(x, li):  # 查询有序数列li中不大于数字x的最大项    mid = (len(li)-1)//2  # 采用二分法限制搜索区间,并进行递归    if x < li[mid]:        return find_i(x, li[:mid+1])    elif x > li[mid+1]:        return find_i(x, li[mid:])    elif x == li[mid+1]:        return li[mid+1]    else:        return li[mid]def long_i(i, q, li):  # 获取首项为有序列表第i项时,对应的完美数列长度    M = li[i] * q    if M >= li[-1]:        long = len(li) - i    else:        M = find_i(M, li[i:])        M_i = li.index(M)        long = M_i + 1 - i    return longN,q = map(int, input().split())  #  输入参数li = list(map(int, input().split()))  #输入数据if q == 1:  # q=1时,显然完美数列长度为1    print('1')else:    li.sort()  # 升序数列    low = li[-1]//q    if low < li[0]:  # 整个数列都满足完美数列的条件,直接输出N        print(str(N))    else:        rounds = li.index(find_i(low, li)) + 2  # 最小值所在项的循环次数        score = 0        for i in range(rounds):            m = long_i(i, q, li)            if score < m:                score = m        print(m)

0 0
原创粉丝点击