多校冲刺 NOIP 20211104 模拟 (22)

T1

首先可以把阶乘的形式化为\(\prod_{i=a+1}^{b}i\)的形式

不难发现对于每一个数,当\(b-a\)固定时, a 和 b 也是固定的,且 b-a 最大只有20

于是就可以枚举 b-a,然后二分出 a,复杂度\(Tw\log n\),w=20

T2

\(\frac{n}{k}\)为偶数时可以一条龙接上去

为奇数时沿用这个想法,考虑如何调整,发现要做的就是将前面的和制作出一个(排序后的)等差数列才能与最后一行抵消

然后就没了,注意一些无解和特判

T3

首先将操作和询问离线,维护一个以操作编号为下标的树状数组,然后在基岩上做扫描线

每个操作,在扫到的点是其左端点时,在编号的位置加上\(h_i\),否则减去

回答询问在树状数组上二分出第一个前缀和大于 y 的位置,直接写是\(O(q\log^2n)\)

T4

由于删掉想(x,y)后 x 的排水量不变

可以将删一条边看做是 y 减少了一些排水量,x 的其他出边增加了一些排水量

更简便地,可以在 x 加上同时在 y 上减去以降低复杂度

代码

T1

#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
struct ans_ {
    int a, b;
} vct[21];
int n;
inline int read() {
    int s = 0;
    char ch = getchar();
    while (ch > '9' || ch < '0') ch = getchar();
    while (ch >= '0' && ch <= '9') {
        s = (s << 1) + (s << 3) + (ch ^ 48);
        ch = getchar();
    }
    return s;
}
int check(int x, int y) {
    int a = 1, b = 1;
    for (int i = 1; i <= y; ++i) {
        b = a;
        a *= (i + x - 1);
        if (a / (i + x - 1) != b || a > n)
            return 0;
    }
    return a;
}
void two(int x, int y) {
    int l = 1, r = sqrt(x);
    int ans = 1, mid;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (!check(mid, y))
            r = mid - 1;
        else
            l = mid + 1, ans = mid;
    }
    if (ans == 1)
        return;
    if (check(ans, y) == x)
        vct[y] = { ans + y - 1, ans - 1 };
    return;
}
signed main() {
    FILE* x = freopen("factorial.in", "r", stdin);
    x = freopen("factorial.out", "w", stdout);
    int t = read();
    int st, num;
    while (t--) {
        for (int i = 1; i <= 20; ++i) vct[i] = { 0, 0 };
        num = 1;
        n = read();
        if (n == 1)
            printf("-1\n");
        else {
            vct[1] = { n, n - 1 };
            st = sqrt(n);
            if (st * (st + 1) == n && st != 1)
                vct[2] = { st + 1, st - 1 }, ++num;
            for (int i = 3; i <= 20; ++i) {
                two(n, i);
                if (vct[i].a)
                    ++num;
            }
            printf("%lld\n", num);
            for (int i = 20; i; --i)
                if (vct[i].a)
                    printf("%lld %lld\n", vct[i].a, vct[i].b);
        }
    }
    return 0;
}

T2

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 11;
int n, k;
long long sum[N];
vector<int> vct[N];
inline int read() {
    int s = 0;
    char ch = getchar();
    while (ch > '9' || ch < '0') ch = getchar();
    while (ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s;
}
int main() {
    FILE* x = freopen("subset.in", "r", stdin);
    x = freopen("subset.out", "w", stdout);
    int t = read();
    while (t--) {
        n = read();
        k = read();
        if (k == 1) {
            printf("Yes\n");
            for (int i = 1; i <= n; ++i) printf("%d ", i);
            printf("\n");
            continue;
        }
        if (k == n)
            printf("No\n");
        else if (!((n / k) & 1)) {
            printf("Yes\n");
            for (int i = 1; i <= n; ++i) vct[i].clear();
            for (int i = 1; i <= n / k; ++i) {
                if (i & 1)
                    for (int j = 1; j <= k; ++j) vct[j].push_back((i - 1) * k + j);
                else
                    for (int j = k; j; --j) vct[j].push_back(i * k - j + 1);
            }
            for (int j = 1; j <= k; ++j, printf("\n"))
                for (int i = 1; i <= n / k; ++i) printf("%d ", vct[j][i - 1]);
        } else {
            if (!(k & 1))
                printf("No\n");
            else {
                printf("Yes\n");
                for (int i = 1; i <= n; ++i) vct[i].clear();
                for (int i = 1; i <= n / k; ++i) {
                    if (i & 1)
                        for (int j = 1; j <= k; ++j) vct[j].push_back((i - 1) * k + j);
                    else
                        for (int j = k; j; --j) vct[j].push_back(i * k - j + 1);
                }
                for (int i = 1; i <= k / 2; ++i) vct[i][0] = k / 2 - i + 1;
                for (int i = k / 2 + 1; i <= k; ++i) vct[i][0] = k - i + k / 2 + 1;
                long long a = 0;
                for (int i = 1; i <= 3 * k; ++i) a += i;
                a /= k;
                for (int i = 1; i <= k; ++i) sum[i] = vct[i][0] + vct[i][1];
                for (int i = 1; i <= k; ++i) vct[i][2] = a - sum[i];
                for (int j = 1; j <= k; ++j, printf("\n"))
                    for (int i = 1; i <= n / k; ++i) printf("%d ", vct[j][i - 1]);
            }
        }
    }
    return 0;
}

T3

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 11;
struct hi_ {
    int id;
    int hi;
};
vector<hi_> vctl[N];
vector<hi_> vctr[N];
vector<hi_> qry[N];
int n, q;
int tre[N];
int ans[N];
inline int lowbit(int x) { return x & -x; }
inline int read() {
    int s = 0;
    char ch = getchar();
    while (ch > '9' || ch < '0') ch = getchar();
    while (ch >= '0' && ch <= '9') {
        s = (s << 1) + (s << 3) + (ch ^ 48);
        ch = getchar();
    }
    return s;
}
void insert(int x, int h) {
    while (x <= q) tre[x] += h, x += lowbit(x);
    return;
}
int query(int x) {
    int sum = 0;
    while (x) sum += tre[x], x -= lowbit(x);
    return sum;
}
void get_ans(int x, int h) {
    int l = 0, r = x - 1;
    int mid, as = 0;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (query(mid) >= h)
            as = mid, r = mid - 1;
        else
            l = mid + 1;
    }
    ans[x] = as ? as : -1;
    return;
}
signed main() {
    FILE* p = freopen("concrete.in", "r", stdin);
    p = freopen("concrete.out", "w", stdout);
    n = read(), q = read();
    for (int ty, l, r, h, x, y, i = 1; i <= q; ++i) {
        ty = read();
        if (ty == 1)
            l = read(), r = read(), h = read(), vctl[l].push_back({ i, h }), vctr[r].push_back({ i, h });
        else
            x = read(), y = read(), qry[x].push_back({ i, y });
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < vctl[i].size(); ++j) insert(vctl[i][j].id, vctl[i][j].hi);
        for (int j = 0; j < qry[i].size(); ++j) get_ans(qry[i][j].id, qry[i][j].hi);
        for (int j = 0; j < vctr[i].size(); ++j) insert(vctr[i][j].id, -vctr[i][j].hi);
    }
    for (int i = 1; i <= q; ++i)
        if (ans[i])
            printf("%lld\n", ans[i] == -1 ? 0 : ans[i]);
    return 0;
}

T4

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5 + 11;
const int mod = 998244353;
struct qxxx {
    int v, next, w;
} cc[N];
int n, m, r, k;
int ans[N];
int inv[N];
int rd[N], cd[N], sum[N], w[N], tem[N];
int first[N], cnt;
queue<int> dui;
inline void md(int& x) {
    if (x >= mod)
        x -= mod;
    return;
}
inline int read() {
    int s = 0;
    char ch = getchar();
    while (ch > '9' || ch < '0') ch = getchar();
    while (ch >= '0' && ch <= '9') {
        s = (s << 1) + (s << 3) + (ch ^ 48);
        ch = getchar();
    }
    return s;
}
int fm(int x, int y) {
    int as = 1;
    while (y) {
        if (y & 1)
            as = as * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return as;
}
void qxx(int u, int v, int w) {
    cc[++cnt] = { v, first[u], w };
    first[u] = cnt;
    return;
}
signed main() {
    FILE* p = freopen("water.in", "r", stdin);
    p = freopen("water.out", "w", stdout);
    n = read(), m = read();
    r = read(), k = read();
    int x, y, si = 0;
    for (int z, i = 1; i <= k; ++i) {
        x = read(), y = read(), z = read();
        md(si += z);
        qxx(x, y, z);
        ++rd[y], ++cd[x];
        ++tem[y];
    }
    si = fm(si, mod - 2);
    for (int i = 1; i <= n; ++i) inv[i] = fm(i, mod - 2);
    for (int i = 1; i <= m; ++i) dui.push(i), sum[i] = 1;
    int ny, nyh;
    while (dui.size()) {
        x = dui.front();
        dui.pop();
        ny = inv[cd[x]];
        nyh = inv[cd[x] - 1];
        for (int i = first[x]; i; i = cc[i].next) {
            y = cc[i].v;
            --tem[y];
            md(sum[y] += sum[x] * ny % mod);
            md(w[x] += cc[i].w * sum[x] % mod * cd[x] % mod * (nyh - ny + mod) % mod);
            md(w[y] += mod - cc[i].w * sum[x] % mod * nyh % mod);
            if (!tem[y])
                dui.push(y);
        }
    }
    for (int i = 1; i <= m; ++i) dui.push(i);
    while (dui.size()) {
        x = dui.front();
        dui.pop();
        for (int i = first[x]; i; i = cc[i].next) {
            y = cc[i].v;
            --rd[y];
            md(w[y] += w[x] * inv[cd[x]] % mod);
            if (!rd[y])
                dui.push(y);
        }
    }
    for (int i = n - r + 1; i <= n; ++i) md(sum[i] += w[i] * si % mod), printf("%lld ", sum[i]);
    return 0;
}
上一篇:NOIP 模拟 九十


下一篇:NOIP 模拟八十九