[アルゴリズムとデータ構造]第2回 計算量
計算量を学ぼう!
ぱうえる(けんた):link:
速いコードが書きたい!
でも速いコードってどうやって評価する??
- 「
個のデータに対して 秒で終了しました!」 - データの個数が変わったらどうなる??
- そもそもPythonで実行するかC言語で実行するかでも変わりそう
「データの大きさ」や「実行する環境」に依存しない評価方法が必要
→計算量の出番
オーダー記法 (1/2)
では が大きくなったとき
値が大きく変化する- 定数倍を考えないで、
の項だけに
注目すればいいのでは??
→
オーダー記法 (2/2)
- 計算量は基本的にオーダー記法で書く
- 一番大きい項のみ残して表記する
( は定数) - 定数倍は無視する
- 一番大きい項のみ残して表記する
オーダー記法の例)
コードの計算量の調べ方
回のループをする → 回のループの中で 回のループをする(二重ループ)
→- bit全探索(
個の要素についてある/ないの 通りを考える)
→ 個の順列を全て調べる →
ここまでの復習
このコードの計算量は??
## 1~n までの数の和を求める
n = int(input())
ans = 0
for i in range(1, n+1):
ans += i
print(ans)
→
計算量の使い方
- 一般的なコンピュータが1秒間に計算できる回数は約
回 - 競プロの実行時間制限は大体
秒 - 各計算量ごとの、制限時間に間に合う
↓
参考:https://qiita.com/drken/items/872ebc3a2b5caaa4a0d0#1-3-計算量の使い方
計算量を落とすテクニック
今回は代表的なものを2つ紹介します。
式変形
先ほどの
## 1~n までの数の和を求める
n = int(input())
ans = 0
for i in range(1, n+1):
ans += i
print(ans)
式変形
このコードは、
(
等差数列の和の公式を使えば…
## 1~n までの数の和を求める
n = int(input())
ans = n * (n + 1) // 2
print(ans)
なんと、53.7ナノ秒で終了!!
→ 約5億倍の高速化(ちょっと極端な例ではあるけど)
→ もちろん余裕で間に合う
演習問題(式変形)
- Q4. 積の総和 (1)(アルゴ式)
https://algo-method.com/tasks/1019 - ARC107 A - Simple Math(AtCoder)
https://atcoder.jp/contests/arc107/tasks/arc107_a
累積和
あるたい焼き屋さんでは 毎日、売れた個数を記録しています。
営業開始から
→
累積和
あるたい焼き屋さんでは、
営業開始から
このとき、以下の
累積和
各項を毎回足していくと、毎回のクエリで
よって、
→間に合わない!
累積和
そこで、
このとき、
証明)
累積和
つまり??
累積和
累積和配列の計算方法
累積和
累積和の計算量は?
を求めるのに : から まで 回計算する - クエリの計算に
から までの和は という引き算1回で求まる - このクエリを
回繰り返す
→
よって
演習問題(累積和)
- Q3. 駅と駅の距離(アルゴ式)
https://algo-method.com/tasks/1027 - ABC037 C - 総和(AtCoder)
https://atcoder.jp/contests/abc037/tasks/abc037_c
参考
- 計算量オーダーの求め方を総整理! 〜どこからlogが出て来るか〜
https://qiita.com/drken/items/872ebc3a2b5caaa4a0d0 - 累積和を何も考えずに書けるようにする!
https://qiita.com/drken/items/56a6b68edef8fc605821