悲伤的发现自己非常菜,尝试通过补CF题来提高水平(雾。

大概是从去年暑假的CF开始补,基本上尝试Div2的DE, 和Div1的后面 $\leq 2900$

CF1543D diff:2200

首先这是D1/D2. D2与D1的区别在一个 $k=2$ 一个 $k=[1, 100]$
我们发现它所定义的符号在 $k=2$ 时就为异或,我们可以通过这个下手完成D1。
我们开始研究D2的做法。

我们看到 $a \oplus_k b = c$ 这一个式子。

题目中 $x\oplus_kz=y$ 所以我们考虑如何通过 $y$ 来推到 $x$ .

我们发现可以定义 $\ominus$,是操作相反,发现 $y\ominus_kx = z$。

此时我们回到题目,题目要求我们猜测 $x$ 的值。

每一次我们猜测后,$x\oplus_kz=y$ 新值 $z$ 和 原来的 $x$ 符合的式子。

那么根据刚才我们的定义。我们发现新的 $x$ 数值等于 $q_1\ominus_kx$

这是第一次。那么我们可以发现第二次就是$q_2\ominus(q_1\ominus_kx)$

显然我们可以发现 第 $q_i$ 次时 $x$ 的值为

$$ q_{i}\ominus_k(q_{i-1}\ominus_k(q_{i-2}\ominus_k(q_{i - 3}\ominus_k(...\ominus_k(q_1\ominus_k x))))) $$

那么我们想猜测到 $x$ 的值。

发现我们可以询问$n$次。那么我们探究x的规律,使得式子在某时与上面的式子完全吻合。此时我们就找到了答案。

那我们发现

$$ q_{i}\ominus_k(q_{i-1}\ominus_k(q_{i-2}\ominus_k(q_{i - 3}\ominus_k(...\ominus_k(q_1\ominus_k (i-1)))))) $$

当$i = x+1$时式子与上面式子吻合找到答案。

Code

#include <iostream>
#include <cstdio>
#include <cmath>

typedef long long ll;

const int N = 1e5 + 5;

using namespace std;

int n, m, k;

ll ask, sum;

ll add(ll a, ll b) {
    ll ts = 1, res = 0;
    for (int i = 1; i <= 25; i ++ ) {
        if (!a && !b)
            break;
        ll t = (a % k + b % k) % k;
        res += t * ts;
        ts *= k;
        a /= k, b /= k;
    }
    return res;
}

ll su(ll a, ll b) {
    ll ts = 1, res = 0;
    for (int i = 1; i <= 25; i ++ ) {
        if (!a && !b)
            break;
        ll t = (a % k - b % k + k) % k;
        res += t * ts;
        ts *= k;
        a /= k, b /= k;
    }
    return res;
}

int main() {
    int T;
    cin >> T;
    while (T -- ) {
        cin >> n >> k;
        for (int i = 1; i <= n; i ++ ) {
            if (i == 1) {
                sum = 0, ask = 0;
            }
            if (i != 1) {
                if (i % 2) {
                    ask = add(sum, i - 1);
                } else {
                    ask = su(sum, i - 1);
                }
            }
            cout.flush();
            cout << ask << endl;
            cout.flush();
            int r; cin >> r; if (r == 1) {
                break;
            }
            sum = su(ask, sum);
        }
    }
}

话说现在开始大括号不换行了qwq.

CF913E diff:2400

一道神奇的题。题意比较难理解。理解之后,我们可以考虑状压dp。我们用 $f_{i, j, k}$ 表示在 第 $i$ 次下最终答案 $j$ ,优先级为 $k$ 的最短方案。

优先级遵循其规则分为 $0, 1, 2$ $0$ 为 进行 $|$ 的数值。$1$ 为 进行 $\&$ 之后的数值。 $2$ 表示加 $()$ or $!$ 之后的数值。

我们发现可以递推。参照代码的方式可以进行。

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = (1 << 8) + 5, M = 12;

string f[M][N][3];

string good(string x, string y) {
    if (x == "") {
        return y;
    } else if (y == "") {
        return x;
    }
    if (x.size() < y.size()) {
        return x;
    } else if (y.size() < x.size()) {
        return y;
    }
    return x < y ? x : y;
}

string cs(string x, int ms) {
    if (x == "" || x == "|" || x == "!" || x == "&") {
        return "";
    }
    if (ms) {
        return x;
    }
    return "(" + x + ")";
}


string sh(int x) {
    string res = "";
    if (x == 0) {
        return "0";
    }
    while (x) {
        res = char((x % 2) + '0') + res;
        x /= 2;
    }
    return res;
}

int main() {
    f[0][15][2] = 'x';
    f[0][51][2] = 'y';
    f[0][85][2] = 'z';
    for (int i = 0; i < M - 1; i ++ ) {
        for (int j = 0; j < (1 << 8); j ++ ) {
            for (int x = 0; x <= 2; x ++ )
                f[i + 1][j][x] = good(f[i + 1][j][x], f[i][j][x]);
            f[i + 1][j][2] = good(f[i + 1][j][2], good(cs(f[i][j][0], 0), cs(f[i][j][1], 0)));
            f[i + 1][((1 << 8) - 1) ^ j][2] = good(f[i + 1][((1 << 8) - 1) ^ j][2], cs('!' + f[i][j][2], 1));
        }
        for (int j = 0; j < (1 << 8); j ++ ) {
            for (int k = 0; k < (1 << 8); k ++ ) {
                for (int x = 0; x <= 2; x ++ ) {
                    for (int y = 1; y <= 2; y ++ ) {
                        if (f[i][j][x] != "" && f[i][k][y] != "")
                            f[i + 1][j | k][0] = good(f[i + 1][j | k][0], f[i][j][x] + '|' + f[i][k][y]);
                    }
                } 
                for (int x = 1; x <= 2; x ++ ) {
                    for (int y = 2; y <= 2; y ++ ) {
                        if (f[i][j][x] != "" && f[i][k][y] != "") {
                            f[i + 1][j & k][1] = good(f[i + 1][j & k][1], f[i][j][x] + '&' + f[i][k][y]);
                        }
                    }
                } 
            }

        }
    }
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T;
    cin >> T;
    while (T -- ) {
        int n;
        int j = 0;
        cin >> n;
        int k = 1;
        while (n) {
            j += k * (n % 10);
            n /= 10;
            k *= 2;
        }
        cout << good(good(f[M - 1][j][2],f[M - 1][j][1]), f[M - 1][j][0]) << '\n';
    }
    return 0;
}
最后修改:2023 年 11 月 04 日
End.