Codility上的練習(11)

2021-06-27 13:12:03 字數 1638 閱讀 1403

(1)ladder

給定兩個等長的陣列a和b, a[i]和b[i]表示求乙個有a[i]級的梯子,每次上1級或者兩級,上到最高端的方法數對2^b[i]取餘數的結果。

資料範圍:陣列長度 l [1..30000] , a中數字範圍 [1..l], b中數字範圍[1..30]

要求複雜度 時間空間都是o(l)

分析:打表法——我們迴圈可以把0..l的結果都算出來 f[i] = f[i - 1] + f[i - 2]  , f[0] = f[1] = 1。 關鍵點在於取餘數,這個取餘數很特殊,對2^b[i]取餘數,相當於取結果的低b[i] bit。因此我們可以取所有結果的低30位,打好表,輸出時再真正取b[i]位,就能達到o(l)的複雜度了。

// you can also use includes, for example:

// #include const int m = (1 << 30) - 1;

vectorsolution(vector&a, vector&b)

vectorf;

f.resize(m + 1);

f[0] = f[1] = 1;

for (int i = 2; i <= m; ++i)

vectoranswer;

for (int i = 0; i < a.size(); ++i)

return answer;

}

(2) fibfrog

先給了fibonacci的定義f[0] = 0, f[1] = 1, f(m) = f(m - 1) + f(m - 2) if m >= 2。乙隻青蛙想從河岸(-1)跳到對岸(n)。中間有0..n-1這n個位置,有乙個陣列a表示這些位置是否有荷葉 ,0表示沒有,1表示有。青蛙從岸上要跳到荷葉上,通過0個或者多個荷葉跳到對岸,而且只能朝對岸的方向跳——不能往回跳。而且青蛙每次跳的距離必須是乙個fibonacci數,請問青蛙最少幾步跳到對岸?無解返回-1。

資料範圍: n [0..30000]

要求複雜度 :時間o(nlogn),空間o(n)。

分析: 首先我們可以把陣列尾端加乙個1,表示對岸。可以認為首端有乙個1或者認為陣列下標從1開始,我們現在目標是到陣列最後乙個元素,只能通過1且跳的距離是fibonacci數的最小步數。 這是乙個顯然的dp (或者說是bfs)。對於位置i 並且a[i] == 1,我們有 dp[i] = min(dp[i - f[j]]) + 1 其中f[j]是fibonacci數並且滿足a[i - f[j]]==1

因為fibonacci是指數增長的,所以不超過n的fibonacci數是o(logn)個,整個遞推的時間複雜度是o(nlogn)。

// you can also use includes, for example:

// #include int solution(vector&a)

vectoranswer;

answer.resize(n + 1, -1);

answer[0] = 0;

for (int i = 1; i <= n; ++i)

for (int j = 0;(j < f.size()) && (i >= f[j]); ++j) }}

return answer[n];

}

Codility上的練習 (9)

1 countsemiprimes 半質數的定義是恰好兩個質數 可以相同 乘積的數,例如4,6,9,10,14,15,21,22,25,26,都是半質數。給定n,長度為m的等長整數陣列p和q,滿足1 p k q k n,求每個區間 p k q k 之間有多少個半質數。函式頭部 vectorsolut...

Codility上的練習 (14)

1 tieropes 給定n段繩子 乙個正整數陣列,和乙個正整數k,每次只能連線相鄰的兩根繩子,連線好了繩子長度為之前的繩子長度和,並且位置不變,問這麼連線下去,最多能形成多少根長度至少為k的繩子?資料範圍 n 1.10 5 陣列元素和k的範圍 1.10 9 要求複雜度 時間o n 空間o 1 分析...

Codility上的練習 (15

1 numbersolitaire 乙個遊戲是從一排n個格仔開始,格仔編號0.n 1,起初,棋子在a 0 每個格仔裡有乙個整數 可能正,可能負 你在格仔i,你扔骰子,得到點數x 1.6 然後走到編號為i x的格仔,如果這個格仔不存在就再投一次骰子,直到i x號格仔存在。你走到n 1號格仔時,遊戲結束...