2021牛客暑期多校训练营2 个人补题记录

比赛链接:Here

本场 3道签到题可还行,2333

A - Arithmetic Progression

B - Cannon

C - Draw Grids (签到)

题意很简单就不翻译了


手写下 \(n = 1\) 的各个情况,然后拓展到 \(n = 2,3,4\) 就清晰了解法,

只要 \(n,m\) 存在一个偶数,先手必胜

简单来说当一个图上有n个点和n条边的时候,一定成环,感觉这题数据可以再大一点。

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    cout << (n % 2 == 0 || m % 2 == 0 ? "YES" : "NO");
}

D - Er Ba Game (签到)

细节题,注意区分各种情况

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int _; for (cin >> _; _--;) {
        int a1, b1, a2, b2;
        cin >> a1 >> b1 >> a2 >> b2;
        if (a1 > b1)swap(a1, b1);
        if (a2 > b2)swap(a2, b2);
        if (a1 == a2 && b1 == b2) {cout << "tie" << endl; continue;}
        if (a1 == 2 && b1 == 8 && !(a2 == 2 && b2 == 8)) {cout << "first" << endl; continue;}
        if (!(a1 == 2 && b1 == 8) && a2 == 2 && b2 == 8) {cout << "second" << endl; continue;}
        if (a1 == b1 && a2 == b2) {cout << "tie" << endl; continue;}
        if (a1 == b1 && a2 != b2) {cout << "first" << endl; continue;}
        if (a1 != b1 && a2 == b2) {cout << "second" << endl; continue;}
        int t1 = (a1 + b1) % 10, t2 = (a2 + b2) % 10;
        if (t1 > t2) {cout << "first" << endl; continue;}
        if (t1 < t2) {cout << "second" << endl; continue;}
        if (b1 > b2) {cout << "first" << endl; continue;}
        if (b1 < b2) {cout << "second" << endl; continue;}
        cout << "tie" << endl;
    }
}

F - Girlfriend (数学)

淦,又是一道数学题。

补题的时候发现比杭电第一场的简单点

题意就不写了

符合条件的显然是两个球的相交。设两点分别为 \((x_1,y_1,z_1),(x_2,y_2,z_2)\) ,那么根据题意,\((x,y,z)\) 需要满足:

\[\sqrt{(x-x_1)^2 + (y-y_1)^2+(z-z_1)^2}\ge k\sqrt{(x-x_2)^2 + (y-y_2)^2+(z-z_2)^2} \\转化形式\\ (x+\frac{x_1-k^2x_2}{k_2-1})+(y+\frac{y_1-k^2y_2}{k_2-1})+(z+\frac{z_1-k^2z_2}{k_2-1})\le\sqrt{\frac{x_1^2+y_1^2+z_1^2 - k^2x_2^2 - k^2y_2^2-k^2z_2^2}{k^2-1}+(\frac{x_1-k^2x_2}{k_2-1})^2+(\frac{y_1-k^2y_2}{k_2-1})^2+(\frac{z_1-k^2z_2}{k_2-1})^2} \]

那么球心坐标为:\((\frac{k^2x_2-x_1}{k^2-1},\frac{k^2y_2-y_1}{k^2-1},\frac{k^2z_2-z_1}{k^2-1})\)

半径为:\(\sqrt{\frac{x_1^2+y_1^2+z_1^2 - k^2x_2^2 - k^2y_2^2-k^2z_2^2}{k^2-1}+(\frac{x_1-k^2x_2}{k_2-1})^2+(\frac{y_1-k^2y_2}{k_2-1})^2+(\frac{z_1-k^2z_2}{k_2-1})^2}\)


【AC Code】码 Latex 好累呀...

const double pi = acos(-1);
double x[5], y[5], z[5];
double k1, k2;
void solve(double x1, double y1, double z1, double r1, double x2, double y2, double z2, double r2) {
    double ans = 0;
    double dis = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
    if (dis >= r1 + r2) ans = 0;
    else if (dis + r1 <= r2) ans = (4.00 / 3.00) * pi * r1 * r1 * r1;
    else if (dis + r2 <= r1) ans = (4.00 / 3.00) * pi * r2 * r2 * r2;
    else {
        double cal = (r1 * r1 + dis * dis - r2 * r2) / (2.00 * dis * r1);
        double h = r1 * (1 - cal);
        ans += (1.00 / 3.00) * pi * (3.00 * r1 - h) * h * h;
        cal = (r2 * r2 + dis * dis - r1 * r1) / (2.00 * dis * r2);
        h = r2 * (1.00 - cal);
        ans += (1.00 / 3.00) * pi * (3.00 * r2 - h) * h * h;
    }
    printf("%.3f\n", ans);
}
int read() {
    int x = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
    while (c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}
    return x * f;
}
int main() {
    int T = read();
    while (T--) {
        for (int i = 0; i < 4; i++) x[i] = read(), y[i] = read(), z[i] = read();
        k1 = read(), k2 = read();
        double c1x, c1y, c1z, c1r, t;
        c1x = (k1 * k1 * x[1] - x[0]) / (k1 * k1 - 1);
        c1y = (k1 * k1 * y[1] - y[0]) / (k1 * k1 - 1);
        c1z = (k1 * k1 * z[1] - z[0]) / (k1 * k1 - 1);
        t = k1 * k1 * ((x[1] * x[1]) + (y[1] * y[1]) + (z[1] * z[1])) - x[0] * x[0] - y[0] * y[0] - z[0] * z[0];
        t /= (k1 * k1 - 1);
        c1r = sqrt(c1x * c1x + c1y * c1y + c1z * c1z - t);

        double c2x, c2y, c2z, c2r;
        c2x = (k2 * k2 * x[3] - x[2]) / (k2 * k2 - 1);
        c2y = (k2 * k2 * y[3] - y[2]) / (k2 * k2 - 1);
        c2z = (k2 * k2 * z[3] - z[2]) / (k2 * k2 - 1);
        t = k2 * k2 * ((x[3] * x[3]) + (y[3] * y[3]) + (z[3] * z[3])) - x[2] * x[2] - y[2] * y[2] - z[2] * z[2];
        t /= (k2 * k2 - 1);
        c2r = sqrt(c2x * c2x + c2y * c2y + c2z * c2z - t);
        solve(c1x, c1y, c1z, c1r, c2x, c2y, c2z, c2r);
    }
    return 0;
}

不过本题似乎有其他数学写法,欢迎补充

G - League of Legends

H - Olefin

I - Penguins (搜索)

题意大意:

两个 \(20 \times 20\) 的地图,两个玩家操作的角色分别需要从 \((20,20),(20,1)\) 走到 \((1,20),(1,1)\),同时需在地图上用 A 记录最短路径并输出


裸的 BFS 保存路径的搜索?

我这里把两个图一起搜了,如果怕写乱也可拆开来跑两次BFS

【AC Code】注意细节

const int N = 30, inf = 0x3f3f3f3f;
char e1[N][N], e2[N][N], path[N * N * 2], dir[] = {'D', 'L', 'R', 'U'};
int cnt;
struct node {
    int x1, y1, x2, y2;// 当前坐标
} pre[N][N][N][N];
int d[N][N][N][N], p[N][N][N][N];
int Dir[4][4] = {1, 0, 1, 0, 0, -1, 0, 1, 0, 1, 0, -1, -1, 0, -1, 0};

void BFS() {
    queue<node>q;
    memset(d, inf, sizeof(d));
    d[20][20][20][1] = 0;
    q.push(node{20, 20, 20, 1});
    while (!q.empty()) {
        node tmp = q.front();
        q.pop();
        int x1 = tmp.x1, y1 = tmp.y1, x2 = tmp.x2, y2 = tmp.y2;
        int dis = d[x1][y1][x2][y2];
        for (int i = 0; i < 4; ++i) {
            int u1 = x1 + Dir[i][0], v1 = y1 + Dir[i][1];
            int u2 = x2 + Dir[i][2], v2 = y2 + Dir[i][3];
            if (e1[u1][v1] != '.')u1 -= Dir[i][0], v1 -= Dir[i][1];
            if (e2[u2][v2] != '.')u2 -= Dir[i][2], v2 -= Dir[i][3];
            if (dis + 1 < d[u1][v1][u2][v2]) {
                d[u1][v1][u2][v2] = dis + 1;
                pre[u1][v1][u2][v2] = node{x1, y1, x2, y2};
                p[u1][v1][u2][v2]  = i;
                q.push(node{u1, v1, u2, v2});
            }
        }
    }
}

void solve(node u) {
    int x1 = u.x1, y1 = u.y1, x2 = u.x2, y2 = u.y2;
    e1[x1][y1] = e2[x2][y2] = 'A';
    if (x1 == 20 and y1 == 20 and x2 == 20 and y2 == 1)return ;
    solve(pre[x1][y1][x2][y2]);
    path[cnt++] = dir[p[x1][y1][x2][y2]];
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    for (int i = 1; i <= 20; ++i)scanf("%s %s", e1[i] + 1, e2[i] + 1);
    BFS();
    solve(node{1, 20, 1, 1});
    cout << cnt << "\n" << path << "\n";
    for (int i = 1; i <= 20; ++i)printf("%s %s\n", e1[i] + 1, e2[i] + 1);
}

J - Product of GCDs

K - Stack (签到)

比赛时,学长指出K题是构造一个前 \(p_i\) 个数中非降子序列长度为 \(a_i\) 的数组

但细节上没处理好。

这道题实际上可直接模拟,先填好给出的 \(k\) 个位置,然后补充空位 if (!a[i])a[i] = a[i - 1] + 1;

但填充过程发现 if (a[i] > a[i - 1] + 1) 则可以直接输出 -1

剩下就是直接模拟题意了

另外 K神 有一个树状数组的解法,值得学习一下

const int N = 1e6 + 10;
int a[N];
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, k;
    cin >> n >> k;
    while (k--) {
        int x, y; cin >> x >> y;
        a[x] = y;
    }
    for (int i = 1; i <= n; ++i) {
        if (!a[i])a[i] = a[i - 1] + 1;
        else if (a[i] > a[i - 1] + 1) {
            cout << -1;
            return 0;
        }
    }

    stack<int>stk;
    int t = 1;
    for (int i = n; i > 0; --i) {
        while (stk.size() < a[i])stk.push(t++);
        a[i] = stk.top(); stk.pop();
    }
    for (int i = 1; i <= n; ++i)
        cout << a[i] << " \n"[i == n];
}

L - WeChat Walk

posted @ 2021-07-21 21:26  RioTian  阅读(139)  评论(0编辑  收藏  举报