“粉刷天花板”天池在线编程测试赛题九章算法题解题思路

你想给自己盖栋房子。房子是正方形或长方形的,它的长和宽需要属于集合s,并且其面积不超过a。请问有多少组可能的长宽的组合?
集合s的n个元素的计算方法如下,给定了一个种子s0,和参数k,b和m,并通过以下公式计算:
Si=((k*Si-1+b) mod m+ 1+Si-1) 1<=i<n

样例
样例 1

输入:
s_0 = 2
n = 3
k = 3
b = 3
m = 2
a = 15
输出: 5
说明:
对于样例,给定了s0=2和总长度n=3,同时还有k=3、 b=3 和 m=2:

现在我们有了长度的集合,我们可以暴力的计算答案,当a=15时,有:

s = [2,4,6]s=[2,4,6]

思路:

  • 首先按照题意先把集合s计算出来。
  • 并按照升序排列
  • 下一步开始计算结果。

解法1: 双循环的暴力遍历(×)

def solve(s0,k,b,m,n,a):
    list1=[s0]
    temp=s0
    for x in range(n-1):#算出全部数组
        temp=(k*temp+b)%m+1+temp
        list1.append(temp)
    list1.sort()  #排序
    print(list1)
    
    sum=0
    for x in range(n):
        for y in range(n):  #因为要包括正方形
            if (list1[x]*list1[y])<=a:
                sum+=1
#                 print(list1[x],list1[y],'True')
            else:
#                 print(list1[x],list1[y],'False')
                break  #已经超了,后面不必再算了
    print(sum)        
solve(2,3,3,2,3,15)

解法2:左右双指针(√)

解题思路:以如下结果集s为例,a=60
[2, 4, 6, 8, 10, 12, 14, 16]

设定左右两个指针

初始时 左指针指向2,右指针指向16
计算 216是否超过a
如果超过了,则 右指针减一 ,重新循环
如果没超过,则开始计算 左指针到右指针中间这块数据会产生多少种结果
以左指针2 右指针16 为例,
right=7
left=0
right-left=7
7
2=14
也就是
集合[[2,4],[2,6],[2,8],[2,10],[2,12],[2,14],[2,16],[4,2],[6,2],[8,2],[10,2],[12,2],[14,2],[16,2]]
最后别忘了还有一个 [2,2]

然后 右指针不动,左指针加一,再开始一轮

def painttheCeiling(s0, n, k, b, m, a):

    list1=[s0]
    temp=s0
    for x in range(n-1):
        temp=(k*temp+b)%m+1+temp
        list1.append(temp)
    list1.sort()

    sum=0       
    left=0
    right=n-1    
    
    while True:
        if left==right: #撞上的时候就可以结束循环了
            if (list1[left]*list1[right])<=a:
                sum+=1
            break
        if (list1[left]*list1[right])>a:
            right-=1
        else:
            sum=sum+(right-left)*2+1  #解法的数量有规律
            left+=1
        return sum
    
painttheCeiling(2,8,3,3,2,60)

posted on 2020-08-27 13:15  耀扬  阅读(363)  评论(0)    收藏  举报

导航