AtCoder Grand Contest 020

 

tourist's contest...ssfd

 

A - Move and Win

想不到好的博弈方法,我就直接暴力了...
可以确定的是,如果一个人觉得他走这个方向是最优的,那么他肯定会一直走下去。
那么就枚举四种情况,第一个人往左(往右),第二个人往左(往右)。
当第一个人往左(或往右)时,另一个人怎么走都输时他就能赢,否则他就输了。
看了别人的代码,好像判一下 $b - a$ 的奇偶性就行了..........
好像是的,因为每个人走完一步之后,之间的差的奇偶性还是不改变。
我傻逼了。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, a, b;
    scanf("%d%d%d", &n, &a, &b);
    bool ans1 = 0, ans2 = 0, ans3 = 0, ans4 = 0;
    for (int i = a, j = b, l = -1, r = -1; i != j; ) {
        if (i + l == 0) l = 1;
        if (i + l == j) {
            ans1 = 0;
            break;
        }
        i += l;
        if (j + r == i) {
            ans1 = 1;
            break;
        }
        j += r;
    }
    for (int i = a, j = b, l = -1, r = 1; i != j; ) {
        if (i + l == 0) l = 1;
        if (i + l == j) {
            ans2 = 0;
            break;
        }
        i += l;
        if (j + r > n) r = -1;
        if (j + r == i) {
            ans2 = 1;
            break;
        }
        j += r;
    }
    for (int i = a, j = b, l = 1, r = -1; i != j; ) {
        if (i + l == 0) l = 1;
        if (i + l == j) {
            ans3 = 0;
            break;
        }
        i += l;
        if (j + r > n) r = -1;
        if (j + r == i) {
            ans3 = 1;
            break;
        }
        j += r;
    }
    for (int i = a, j = b, l = 1, r = 1; i != j; ) {
        if (i + l == 0) l = 1;
        if (i + l == j) {
            ans4 = 0;
            break;
        }
        i += l;
        if (j + r > n) r = -1;
        if (j + r == i) {
            ans4 = 1;
            break;
        }
        j += r;
    }
    if ((ans1 && ans2) || (ans3 && ans4))
        puts("Alice");
    else 
        puts("Borys");
}
View Code

 

B - Ice Rink Game

相当于一个数 $x$,每次进行一次 $\lfloor$$\dfrac{x}{a_i}$$\rfloor$ $\times a_i$,最后 $x$ 变成 $2$。
倒着进行这个过程,最小化答案的话一定是 $a_i$ 的整数倍,最大化答案的话一定是 $a_i$ 的整数倍加上 $a_i - 1$。
那么就倒着递推就好了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 1e5 + 7;
ll a[N];
int n;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
    }
    ll ans1 = 2, ans2 = 2;
    for (int i = n; i >= 1; i--) {
        ans1 = (ans1 - 1) / a[i] + 1, ans2 = ans2 / a[i];
        if (ans1 > ans2) {
            puts("-1");
            return 0;
        }
        ans1 *= a[i];
        ans2 = ans2 * a[i] + a[i] - 1;
    }
    printf("%lld %lld\n", ans1, ans2);
    return 0;
}
View Code

 

C - Median Sum

如果 $S_0$ 也被计入答案的话,那么中位数就肯定是所有答案里面的中位数。
因为对于每一种取法得到的答案 $ans$,肯定存在一个 $sum - ans$。
所有所有数的中位数即是答案的中位数。
除去 $S_0$,答案就在 $\lceil$$\dfrac{sum}{2}$$\rceil$ 往上第一个出现的数。
那么背包一下一个数是否出现。用bitset优化。
复杂度 $O(\dfrac{n ^ 3}{64})$

#include <bits/stdc++.h>
using namespace std;

const int N = 2000 * 2000 + 1;
bitset<N> mask;

int main() {
    int sum = 0;
    int n;
    scanf("%d", &n);
    mask.set(0);
    for (int i = 0, x; i < n; i++) {
        scanf("%d", &x);
        mask = (mask << x) | mask;
        sum += x;
    }
        sum++;
    sum /= 2;
    while (!mask.test(sum)) sum++;
    printf("%d\n", sum);
}
View Code

 

posted @ 2019-10-14 21:57  Mrzdtz220  阅读(139)  评论(0编辑  收藏  举报