(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號格仔時,遊戲結束...