mayoko’s diary

プロコンとかいろいろ。

SRM 671 div1 med:BearDarts

SRM 671 に参加しました。0 完太陽でレートが落ちてしまいました。med は %= MOD するとかいうしょうもないミスで落としたので辛い。

解法

w[a]*w[c] = w[b]*w[d] ということは w[a]/w[b] = w[d]/w[c] ということです。ということで, 座標の最大値が i 以下のもので, w[i]/w[j] (j < i) という形の分数になるものがいくつあるのかを数えながら (a, b, c, d) の組み合わせの個数を数えていけば良いです。

得た知見
  • 下の書き方, 普通に賢いですよね(本番は二分探索した)
    • 「大小関係のある組あわせの数え上げ」で普通に応用できそうなので覚えておこう
class BearDarts {
public:
    long long count(vector <int> w) {
        int n = w.size();
        ll ans = 0;
        map<pii, int> P;
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                int g = __gcd(w[i], w[j]);
                P[pii(w[i]/g, w[j]/g)]++;
            }
            for (int j = i+2; j < n; j++) {
                int g = __gcd(w[i+1], w[j]);
                ans += P[pii(w[i+1]/g, w[j]/g)];
            }
        }
        return ans;
    }
};