G - Ai + Bj + Ck = X (1 <= i, j, k <= N) 解説 by inszva

Using data sruct to count answer

We iterator i from 1 to N. For every i, if we iterator j from 1 to N, there’ll be one solution for \(Ai+Bj\) whose remainder modulo B are same. So we can translate it into a segment operation: add 1 to segment \([Ai+B\), \(Ai+BN]\)(inclusive).
We can properly deal with this before we iterator j and query every \(X-Cj\). This method’s time complex is \(O(NlogN)\).

signed main() {
    int n, a, b, c, x;
    cin >> n >> a >> b >> c >> x;
    vector<tuple<int, int, int>> ev;
    vector<int> bm;
    for (int i = 1; i <= n; i++) {
        int m = a * i % b;
        int l = a * i + b;
        int r = a * i + b * n;
        ev.emplace_back(l, m, 1);
        ev.emplace_back(r+1, m, -1);
        bm.emplace_back(m);
    }
    sort(ev.begin(), ev.end());
    sort(bm.begin(), bm.end());
    bm.erase(unique(bm.begin(), bm.end()), bm.end());
    vector<int> cnt(SZ(bm), 0);
    int t = 0;
    int ans = 0;
    for (int k = n; k >= 1; k--) {
        int y = x - k * c;
        while (t < SZ(ev) && get<0>(ev[t]) <= y) {
            int m = get<1>(ev[t]);
            m = lower_bound(bm.begin(), bm.end(), m) - bm.begin();
            cnt[m] += get<2>(ev[t]);
            t++;
        }
        int m = lower_bound(bm.begin(), bm.end(), y % b) - bm.begin();
        if (m < SZ(cnt) && bm[m] == y % b)
            ans += cnt[m];
    }
    cout << ans << "\n";
    return 0;
}

投稿日時:
最終更新: