跳转至

250810 模拟赛

T1 石子游戏

alt text

好像有一些更强的性质,\(f(n)\) 直接从 \(f(\lfloor \frac nk\rfloor)\) 转移即可。

T2 乘法计数

查询区间 \([1,n]\) 内所有整数的数位乘积共有多少种不同的取值。

\(n\le 10^{18},\ T\le 5\)

注意到由于是前缀查询,因此对每个乘积只需考虑最小的一个数字即可。由此我们有两种做法:第一种是枚举质因子的次数,然后贪心得到最小值;第二种是直接钦定数位单调不降,然后离线扫询问即可。

T4 环形工厂

先贴个 std。

#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <tuple>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#define ll long long
#define pa pair<ll,ll>
#define fi first
#define se second
#define int ll
using namespace std;

const int N = 10004;

int L, n, m;
int st[N], ps[N];
char dr[N];
int du[N];
bool vis[N], occ[N];
int tp[N];
int ans_tp[N], ans_tm[N];

priority_queue<tuple<int,int,int>, vector<tuple<int,int,int>>, greater<tuple<int,int,int>>> ev;

inline int dist(int x, int y) {
    return (y - x + L) % L;
}

inline int rev_id(int x) {
    if (x > m) return x - m;
    return x + m;
}

inline int ori_id(int x) {
    if (x > m) return x - m;
    return x;
}

void add_ev(tuple<int,int,int> e) {
    ev.push(e);
}

struct Tracker {
    multiset<pa> car;
    multiset<pa> fac;

    void add_car(int i, int t) {
        int r = (ps[i] - t % L + L) % L;
        auto it = fac.lower_bound({ps[i], -1e6});
        if (it == fac.end()) it = fac.begin();
        if (it != fac.end()) {
            int tm = t + dist(ps[i], (*it).fi);
            add_ev({tm, i, (*it).se});
        }
        car.insert({r, -i});
    }

    void add_fac(int i, int t, int ins = 0) {
        auto it = car.lower_bound({(tp[i] - t % L + L) % L + 1, -1e6});
        if (!car.empty()) {
            if (it == car.begin()) it = car.end();
            --it;
            if (it != car.end()) {
                int cp = ((it->fi + t) % L);
                int tm = t + dist(cp, tp[i]);
                add_ev({tm, -it->se, i});
            }
        }
        if (ins) fac.insert({tp[i], i});
    }

    void rem_fac(int i, int t) {
        fac.erase({tp[i], i});
        auto it = fac.lower_bound({tp[i], i});
        if (it == fac.end()) it = fac.begin();
        if (it != fac.end()) {
            add_fac(it->se, t);
        }
    }

    void car_arr(int i, int j, int t) {
        car.erase({(tp[j] - t % L + L) % L, -i});
        fac.erase({tp[j], j});
        auto it = fac.lower_bound({tp[j], j});
        if (it == fac.end()) it = fac.begin();
        if (it != fac.end()) {
            add_fac(it->se, t);
        }
        add_ev({t + du[i], -1, ori_id(j)});
    }
};

Tracker cw, ccw;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    freopen("factory.in", "r", stdin);
    freopen("factory.out", "w", stdout);

    cin >> n >> m >> L;

    for (int i = 1; i <= m; i++) {
        cin >> tp[i];
        add_ev({0, -1, i});
        tp[m + i] = (L - tp[i]) % L;
    }

    for (int i = 1; i <= n; i++) {
        cin >> st[i] >> ps[i] >> dr[i] >> du[i];
        add_ev({st[i], i, -1});
        if (dr[i] == '-') {
            ps[i] = (L - ps[i]) % L;
        }
    }

    while (!ev.empty()) {
        auto [t, i, j] = ev.top(); ev.pop();

        if (j == -1) {
            if (dr[i] == '+') cw.add_car(i, t);
            else ccw.add_car(i, t);
            continue;
        }

        if (i == -1) {
            occ[j] = false;
            cw.add_fac(j, t, 1);
            ccw.add_fac(j + m, t, 1);
            continue;
        }

        int j0 = j;
        if (j0 > m) j0 -= m;

        if (vis[i] || occ[j0]) continue;

        ans_tp[i] = tp[j0];
        ans_tm[i] = t;
        vis[i] = true;
        occ[j0] = true;

        if (dr[i] == '+') {
            cw.car_arr(i, j, t);
            ccw.rem_fac(rev_id(j), t);
        } else {
            ccw.car_arr(i, j, t);
            cw.rem_fac(rev_id(j), t);
        }
    }

    for (int i = 1; i <= n; i++) {
        cout << ans_tp[i] << " " << ans_tm[i] << '\n';
    }

    return 0;
}