2020牛客NOIP赛前集训营-提高组(第一场)部分题解

A. 牛牛的方程式

数学题。

考虑 \(ax + by = c\) 有解的充要条件是 \(c|\mathrm{gcd}(a, b)\),于是 \(ax + by\) 可以表示的所有整数即为 \(\mathrm{gcd}(a,b)t\)

代入原式:\(\mathrm{gcd}(a,b)t + cz = d\),它有解的充要条件即是 \(d|\mathrm{gcd}(a, b, c).\)

lli a, b, c, d;

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T; cin >> T;
    while (T --> 0) {
        cin >> a >> b >> c >> d;
        bool ans = false;
        lli g = std::__gcd(a, std::__gcd(b, c));;
        if (g == 0) ans = (d == 0);
        else ans = (d % g == 0);
        cout << (ans ? "YES" : "NO") << endl;
    }
    return 0;
}

B. 牛牛的猜球游戏

宏观考虑每次操作对序列的影响,发现添删后面一个操作就是交换序列中对应的两个位置,添删前面一个操作就是交换序列中对应的两个数。于是在操作过程中维护序列和序列里每个数的位置,然后莫队即可。

const int MAXN = 1e5 + 10;

int n, m;
int blk[MAXN];

struct Qry {
    int l, r, id, ansid;
} qrys[MAXN];
bool cmp1(Qry x, Qry y) {
    if (blk[x.l] == blk[y.l]) return x.r < y.r;
    return blk[x.l] < blk[y.l];
}
bool cmp2(Qry x, Qry y) {
    return x.id < y.id;
}

std::vector<int> anss[MAXN];

struct E { int x, y; } ops[MAXN];

int tmp[10], pos[10];

void Add_back(int tp) {
    int opx = ops[tp].x, opy = ops[tp].y;
    std::swap(pos[tmp[opx]], pos[tmp[opy]]);
    std::swap(tmp[opx], tmp[opy]);
}
void Del_back(int tp) {
    Add_back(tp);
}
void Del_front(int tp) {
    int opx = ops[tp].x, opy = ops[tp].y;
    std::swap(tmp[pos[opx]], tmp[pos[opy]]);
    std::swap(pos[opx], pos[opy]);
}
void Add_front(int tp) {
    Del_front(tp);
}
void CollectAns(int qid) {
    qrys[qid].ansid = qid;
    rep (i, 0, 9) anss[qid].push_back(tmp[i]);
}

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    int siz = (int) sqrt(n);
    rep (i, 1, n) cin >> ops[i].x >> ops[i].y;
    rep (i, 0, 9) pos[i] = tmp[i] = i;
    rep (i, 1, n) {
        blk[i] = (i - 1) / siz + 1;
    }
    rep (i, 1, m) {
        cin >> qrys[i].l >> qrys[i].r; qrys[i].id = i;
    } std::sort(qrys + 1, qrys + 1 + m, cmp1);
    int pl = 1, pr = 0; // [pl, pr]
    for (int i = 1; i <= m; ++i) {
        while (pr < qrys[i].r) Add_back(++pr);
        while (qrys[i].l < pl) Add_front(--pl);
        while (pl < qrys[i].l) Del_front(pl++);
        while (qrys[i].r < pr) Del_back(pr--);
        CollectAns(i);
    }
    std::sort(qrys + 1, qrys + 1 + m, cmp2);
    rep (i, 1, m) {
        rep (j, 0, 9) cout << anss[qrys[i].ansid][j] << ' ';
        cout << endl;
    }
    return 0;
}
posted @ 2021-10-13 11:22  Handwer  阅读(34)  评论(0编辑  收藏  举报