“粉刷天花板”天池線上程式設計測試賽題九章演算法題解題思路
阿新 • • 發佈:2020-08-27
你想給自己蓋棟房子。房子是正方形或長方形的,它的長和寬需要屬於集合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
72=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)