[题解][Codeforces] Round_615_Div. 3 简要题解

Posted chz-hc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解][Codeforces] Round_615_Div. 3 简要题解相关的知识,希望对你有一定的参考价值。

A

简要题意

(ullet) 给出 (a, b, c, n),判断是否存在 (A, B, C) 满足 ((A + B + C = n)(a + A = b + B = c + C))

(ullet) 多组数据,(1 leq t leq 10 ^ 4)(1 leq a, b, c, n leq 10 ^ 8)((a, b, c, n)) 均为正整数,((A, B, C)) 均为非负整数。

做法

(ecause) (a + A = b + B = c +C)

( herefore) (a + A + b + B + c + C = 3 cdot (a + A) = 3 cdot (b + B) = 3 cdot (c + C))

(ecause A + B + C == n)

( herefore a + A + b + B + c + C = a + b + c + n)

( herefore a + b + c + n = 3 cdot (a + A) = 3 cdot (b + B) = 3 cdot (c + C))

(frac{a + b + c+ n}{3} = a + A = b + B = c + C)

(ecause (A, B, C )) 均为非负整数

$ herefore $ (A, B, C geq 0)

[ herefore left{ egin{aligned} frac{a + b + c + n}{3} - a geq 0 \frac{a + b + c + n}{3} - b geq 0 \frac{a + b + c + n}{3} - c geq 0 end{aligned} ight.]

[ herefore ① left{ egin{aligned} frac{a + b + c + n}{3} geq a \frac{a + b + c + n}{3} geq b \frac{a + b + c + n}{3} geq c end{aligned} ight.]

故我们只需判断 ((a + b + c + n) equiv 0 mod 3) 且 满足 ① 。

(Code:)

#include <bits/stdc++.h>


using namespace std;

inline int read() {
    int cnt = 0, opt = 1;
    char ch = getchar();

    for (; ! isalnum(ch); ch = getchar())
        if (ch == '-')  opt = 0;
    for (; isalnum(ch); ch = getchar())
        cnt = cnt * 10 + ch - 48;

    return opt ? cnt : -cnt;
}

int T;

int main() {
    T = read();
    
    while (T --) {
        int a, b, c, n;
        a = read(), b = read(), c = read(), n = read();
        int sum = a + b + c + n;
        if (sum % 3 != 0) {
            puts("NO");
            continue;
        }
        sum /= 3;
        if (a > sum || b > sum || c > sum)
            puts("NO");
        else puts("YES");
            
    }
}

B

简要题意

(ullet) 给出 (n)(n) 个特殊点的坐标 ((x_i, y_i))

(ullet)((0, 0)) 出发, 只能向上‘U‘和向右‘R‘移动,求最优路径,或告知无解。

(ullet) 多组数据,(1 leq t leq 100)(1 leq n leq 1000)(0 leq x_i, y_i leq 1000)

做法

傻逼模拟

显然,((0, 0)) 经过每个点的最优路径,一定是从坐标小的点往坐标大的点移动,故我们把 ((x_i, y_i)) 按照 (x_i) 为第一关键字, (y_i) 为第二次关键字,按从小到大排序时。

若存在 (y_i > y_{i + 1}),那么必然无解。

我们再考虑路径,显然,从 ((x_1, y_1)) -> ((x_2, y_2)) ,路径必然可以为:先向右走 (x_2 - x_1) 步, 再向上走 (y_2 - y_1) 步。

故,对于每 (2) 个坐标 ((x_i, y_i)) -> ((x_{i + 1}, y_{i + 1})) 我们只需要输出 (x_{i + 1} - x_{i})R(y_{i + 1} - y_{i})U

#include <bits/stdc++.h>

const int MaxN = 1000 + 10;

using namespace std;

inline int read() {
    int cnt = 0, opt = 1;
    char ch = getchar();

    for (; ! isalnum(ch); ch = getchar())
        if (ch == '-')  opt = 0;
    for (; isalnum(ch); ch = getchar())
        cnt = cnt * 10 + ch - 48;

    return opt ? cnt : -cnt;
}

int T;

struct point {
    int a, b;
} edge[MaxN];

inline int cmp(point x, point y) {
    return x.a == y.a ? x.b < y.b : x.a < y.a;
}

int main() {
    T = read();
    while (T --) {
        int n, opt = 1;
        n = read();
        for (int i = 1; i <= n; ++ i)
            edge[i].a = read(), edge[i].b = read();
        sort(edge + 1, edge + 1 + n, cmp);
        for (int i = 1; i < n; ++ i)
            if (edge[i].b > edge[i + 1].b) {
                puts("NO");
                opt = 0;
                break;
            }
        if (opt == 1)
            puts("YES");
        else continue;
        int x = 0, y = 0;
        for (int i = 1; i <= n; ++ i) {
            for (int j = 1; j <= abs(x - edge[i].a); ++ j)
                printf("R");
            for (int j = 1; j <= abs(y - edge[i].b); ++ j)
                printf("U");
            x = edge[i].a, y = edge[i].b;
        }
        puts("");
    }
}

C

简要题意

(ullet) 给出一个 (n),求 (x, y, z) 满足 ((x cdot y cdot z = n)(x, y, z geq 2)(x ot= y ot= z)),或者告知无解。

(ullet) 多组数据,(1 leq t leq 100)(2 leq n leq 10 ^ 9)

(ullet) 给出 (n)(n) 个特殊点的坐标 ((x_i, y_i))

(ullet)((0, 0)) 出发, 只能向上‘U‘和向右‘R‘移动,问是否可以经过每个特殊点,可以则输出路径。

做法

考虑把 (n) 分解质因数。

(n = prodlimits_{i = 1}^{m} p_{i} ^ {a_i})

分类讨论:

(m geq 3) 时,必存在 ((p_1, p_2, n / p_1 / p_2)) 符合条件。

(m = 2) 时,可能存在 ((p_1, p_2, n / p_1 / p_2)),其中 ((n / p_1 / p_2 geq 2)(n / p_1 / p_2 ot= p_1 ot= p_2))

考虑到 (m = 2)(n / p_1 / p_2 = p_1 ^ {a_1 - 1} cdot p_2 ^ {a_2 - 1})

显然,满足条件的只有(a_1 - 1 + a_2 - 1geq 2),即 (a_1 + a_2 geq 4) 时满足条件。

(m = 1)时,最小的分法也就是((p_1 ^ 1, p_1 ^ 2, p_1 ^ 3))

也就是说,(a_1 geq 1 + 2 + 3),即 (a_1 geq 6) 时满足条件,满足条件的也就是((p_1 ^ 1, p_1 ^ 2, p_1 ^ {a_i - 3}))

#include <bits/stdc++.h>

const int MaxN = 1000000 + 10;

using namespace std;

inline int read() {
    int cnt = 0, opt = 1;
    char ch = getchar();

    for (; ! isalnum(ch); ch = getchar())
        if (ch == '-')  opt = 0;
    for (; isalnum(ch); ch = getchar())
        cnt = cnt * 10 + ch - 48;

    return opt ? cnt : -cnt;
}

int T;
int t, w[MaxN], c[MaxN];

inline void solve(int x) {
    for (int i = 2; i <= sqrt(x); ++ i) {
        if (x % i == 0)
            t ++;
        while (x % i == 0) {
            w[t] = i;
            c[t] ++;
            x /= i;
        }
    }
    if (x > 1)
        w[++ t] = x, c[t] = 1;
}

inline int POW(int x, int y) {
    int cnt = 1;
    while (y) {
        if (y & 1)
            cnt = cnt * x;
        x = x * x;
        y >>= 1;
    }
    return cnt;
}

int main() {
    T = read();
    while (T --) {
        memset(w, 0, sizeof(w));
        memset(c, 0, sizeof(c));
        t = 0;
        int x;
        x = read();
        solve(x);
        if (t >= 3)
            printf("YES
%d %d %d
", POW(w[1], c[1]), POW(w[2], c[2]), x / POW(w[1], c[1]) / POW(w[2], c[2]));

        if (t == 2) {
            if (c[1] + c[2] <= 3) puts("NO");
            else printf("YES
%d %d %d
", w[1], w[2], x / w[1] / w[2]);
        }

        if (t == 1) {
            if (c[1] < 6) puts("NO");
            else printf("YES
%d %d %d
", POW(w[1], 1), POW(w[1], 2), x / POW(w[1], 1) / POW(w[1], 2));
        }


    }
}

D

简要题意

(ullet) 定义数组中的 (MEX) 表示不属于该数组的最小非负整数,(example:[0, 0, 1, 0, 2])(MEX) 就是 (3)

(ullet) 给出 (q, x),您拥有一个空数组 (a[]()即数组中没有元素())

(ullet) 您还得到 (q) 次询问,第 (j) 个询问由一个整数 (y_j) 组成,意味着数组将多一个元素(y_j),查询后长度增加(1)

(ullet) 你可以选择任意元素 (a_i) 并让 (a_i += x)(a_i -= x),且可以操作任意次。

(ullet) 您需要进行以上操作,并且最大化 (a) 数组的 (MEX),并输出。

做法

我们发现答案 (ans) 会修改,一定是存在 (y_j) 通过操作后可以变为 (ans),此时, (ans) 就要加 (1)

我们考虑把 (ans)(y_j) 都修改为最小值,即把 (ans, y_j mod x)

每次把 (y_j mod x) 存入数组。

若存在 (y_j equiv ans mod x),则表示 (y_j) 通过操作后可以变为 (ans),此时,(num[ans mod x] --, ans ++)

#include <bits/stdc++.h>

const int MaxN = 4 * (100000 + 10);

using namespace std;

inline int read() {
    int cnt = 0, opt = 1;
    char ch = getchar();

    for (; ! isalnum(ch); ch = getchar())
        if (ch == '-')  opt = 0;
    for (; isalnum(ch); ch = getchar())
        cnt = cnt * 10 + ch - 48;

    return opt ? cnt : -cnt;
}

int q, x, ans;

int num[MaxN];

int main() {
    q = read(), x = read();

    for (int i = 1; i <= q; ++ i) {
        int m = read();
        num[m % x] ++;

        while (num[ans % x]) {
            -- num[ans % x];
            ans ++;
        }
        printf("%d
", ans);
    }
}

E

咕咕咕

F

咕咕咕

以上是关于[题解][Codeforces] Round_615_Div. 3 简要题解的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #725 (Div. 3) G题解

Codeforces Round #726 div.2 A-F题解

Codeforces Round #720 (Div. 2)题解

Codeforces Round #767 (Div. 2) ABCD题解

[题解][Codeforces] Round_615_Div. 3 简要题解

Codeforces Round #723 (Div. 2)部分题解