昨日のABC344-G、愚直がなんか通りそうな見た目をしています。
問題を読んでない人のために簡単に説明すると、以下が愚直の実装です。q <= 107, n <= 5000。
long long ans = 0; for(int i = 0; i < q; i++) { for(int j = 0; j < n; j++) { ans += (y[j] >= a[i] * x[j] + b[i]); } }
実際、自分のPCで最大ケースを流すと約10秒でした(※自分のPCはジャッジ環境よりもやや性能がよく、実際に愚直を通すのはほとんど無理そうです)。
$ g++ -Ofast -march=native -std=c++17 main.cpp $ time ./a.out real 0m9.967s
さて、競プロしかやらない人には身近ではないかもしれませんが、OpenMPというものがあります。
OpenMP(オープンエムピー)は、並列計算機環境において共有メモリ・マルチスレッド型の並列アプリケーションソフトウェア開発をサポートするために標準化されたAPIである。(Wikipedia)
なんだか難しそうに聞こえるかもしれませんが、使い方は非常に簡単です。
まずは、omp.h
をインクルードします。
#include <omp.h>
次に、おまじないを一行だけ付け加えます。
#pragma omp parallel for reduction(+: ans) for(int i = 0; i < q; i++) { for(int j = 0; j < n; j ++) { ans += (y[j] >= a[i] * x[j] + b[i]); } }
あとは、-fopenmp
オプションをつけてコンパイルするだけです。
$ g++ -Ofast -march=native -std=c++17 -fopenmp main-omp.cpp $ time ./a.out real 0m2.069s
なんと!実行時間が10秒→2秒に短縮されました。うれしいですね~。
さて、じゃあなんでこれが競プロで使えないかという話なんですが、競プロの実行時間はuser timeで評価されるからです。
下の表はOpenMPを使った場合と使わなかった場合のreal/user timeの比較です。
real | user | |
---|---|---|
OpenMPなし | 0m9.874s | 0m9.844s |
OpenMPあり | 0m2.069s | 0m30.183s |
以上、OpenMPというものがあるという話でした。