zoukankan      html  css  js  c++  java
  • Codeforces Round #417 (Div. 2)——ABCE

    题目链接

    题面有点长需耐心读题。

    A.一个人行道上的人被撞有4种情况

    1.所在车道有车驶出

    2.右边车道有左转车

    3.左边车道有右转车

    4.对面车道有直行车

    #include <bits/stdc++.h>
    
    #define rep(i, j, k) for(int i = j;i <= k;i ++)
    
    #define rev(i, j, k) for(int i = j;i >= k;i --)
    
    using namespace std;
    
    typedef long long ll;
    
    int a[4][4];
    
    int main() {
        ios::sync_with_stdio(false);
        rep(i, 0, 3) rep(j, 0, 3) cin >> a[i][j];
        rep(i, 0, 3) {
            if(a[i][3]) {
                rep(j, 0, 2)
                    if(a[i][j]) {
                        puts("YES");
                        return 0;
                    }
                if(a[(i + 1) % 4][0] | a[(i + 2) % 4][1] | a[(i + 3) % 4][2]) {
                    puts("YES");
                    return 0;
                }
            }
        }
        puts("NO");
        return 0;
    }
    View Code

    B.从下往上,每层楼有两种选择——

    左边结束 or 右边结束

    所以有 2^n 种决策

    坑点( Pretest 里有):如果第 k + 1 层到第 n 层楼都已关灯

    那么到第 k 层楼结束就好了

    #include <bits/stdc++.h>
    
    #define rep(i, j, k) for(int i = j;i <= k;i ++)
    
    #define rev(i, j, k) for(int i = j;i >= k;i --)
    
    using namespace std;
    
    typedef long long ll;
    
    int n, m, ans = 666666666;
    
    char s[20][120];
    
    void dfs(int k, int d, int c) {
        if(k >= n) {
            if(d) {
                int t = m;
                rev(i, m - 1, 1)
                    if(s[k][i] == '1') t = i;
                ans = min(ans, c + m - t);
            }
            else {
                int t = 1;
                rep(i, 2, m)
                    if(s[k][i] == '1') t = i;
                ans = min(ans, c + t - 1);
            }
        }
        else {
            if(d) {
                int t = m;
                rev(i, m - 1, 1)
                    if(s[k][i] == '1') t = i;
                dfs(k + 1, 1, c + 2 * (m - t) + 1);
                dfs(k + 1, 0, c + m);
            }
            else {
                int t = 1;
                rep(i, 2, m)
                    if(s[k][i] == '1') t = i;
                dfs(k + 1, 0, c + 2 * (t - 1) + 1);
                dfs(k + 1, 1, c + m);
            }
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n >> m, m += 2;
        rep(i, 1, n) cin >> (s[n + 1 - i] + 1);
        rev(i, n, 1) {
            int flag = 1;
            rep(j, 1, m) {
                if(s[i][j] == '1') {
                    flag = 0;
                    break;
                }
            }
            if(flag) n --;
            else break;
        }
        if(!n) cout << "0";
        else dfs(1, 0, 0), cout << ans;
        return 0;
    }
    View Code

    C.显然 T 随 k 单调递增

    所以直接二分 k 就好了 (蠢了多写了个cmp

    O(nlog^2n) cf 的评测机还是很稳的

    #include <bits/stdc++.h>
    
    #define rep(i, j, k) for(int i = j;i <= k;i ++)
    
    #define rev(i, j, k) for(int i = j;i >= k;i --)
    
    using namespace std;
    
    typedef long long ll;
    
    int n, m, ans = 666666666;
    
    char s[20][120];
    
    void dfs(int k, int d, int c) {
        if(k >= n) {
            if(d) {
                int t = m;
                rev(i, m - 1, 1)
                    if(s[k][i] == '1') t = i;
                ans = min(ans, c + m - t);
            }
            else {
                int t = 1;
                rep(i, 2, m)
                    if(s[k][i] == '1') t = i;
                ans = min(ans, c + t - 1);
            }
        }
        else {
            if(d) {
                int t = m;
                rev(i, m - 1, 1)
                    if(s[k][i] == '1') t = i;
                dfs(k + 1, 1, c + 2 * (m - t) + 1);
                dfs(k + 1, 0, c + m);
            }
            else {
                int t = 1;
                rep(i, 2, m)
                    if(s[k][i] == '1') t = i;
                dfs(k + 1, 0, c + 2 * (t - 1) + 1);
                dfs(k + 1, 1, c + m);
            }
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n >> m, m += 2;
        rep(i, 1, n) cin >> (s[n + 1 - i] + 1);
        rev(i, n, 1) {
            int flag = 1;
            rep(j, 1, m) {
                if(s[i][j] == '1') {
                    flag = 0;
                    break;
                }
            }
            if(flag) n --;
            else break;
        }
        if(!n) cout << "0";
        else dfs(1, 0, 0), cout << ans;
        return 0;
    }
    View Code

    E.(题解说的比较清楚了其实,学习了已一发题解)

    我们很熟悉最基础的求异或和的Nim游戏

    现在我们添加一条规则,对于当前将要操作的玩家

    他任选一堆除了拿走正数数量的石子外

    他还可以在这堆上添加正数数量的石子

    对于这个变种游戏,可以考虑它可以直接转化为最基础的Nim游戏

    因为原来的胜者在对方选择添加石子的操作后

    他可以再把对方添加的石子拿走...

    各操作一轮下来相当于啥也没干...

    把这些啥也没干的过程去掉就是原始的Nim游戏

    我们考虑这个E题

    把所有叶子节点染成蓝色

    蓝点的父亲染红,红点的父亲染蓝

    (为防止矛盾所以保证了所有叶节点与树根距离同奇偶)

    我们可以发现,蓝点就是我们的Nim游戏

    而红点可以传递苹果给蓝点

    就是我们上面新加的不影响结果的规则

    (也可以考虑为,红点的苹果传递到叶子节点需要奇数次传递

    然后再被后手玩家一次吃光,总共经历了偶数步,不影响结果

    而对于蓝色的叶子节点,就只有被拿走的选择

    蓝色的非叶子节点,传递给下面的红点等价于被拿走,因为那不再影响结果

    所以这已经是Nim游戏,每个蓝色节点即为一堆)

    这样我们计算蓝点的异或和 sum

    sum = 0,初始局面后手稳赢

    那他就随便蓝蓝互换,红红互换

    红蓝互换当且仅当两个节点苹果数相同

    sum != 0,需交换蓝 u 和红 v

    当且仅当 sum ^ apple[u] ^ apple[v] = 0

    #include <bits/stdc++.h>
    
    #define rep(i, j, k) for(int i = j;i < (k + 1);i ++)
    
    using namespace std;
    
    long long ans, c0, c1;
    
    int n, md, ret, d[100010], a[100010], f[100010], c[10000010];
    
    vector <int> e[100010];
    
    void dfs(int u, int dep) {
        d[u] = dep, md = max(md, dep);
        rep(i, 0, e[u].size() - 1)
            dfs(e[u][i], dep + 1);
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n;
        rep(i, 1, n) cin >> a[i];
        rep(i, 2, n) cin >> f[i], e[f[i]].push_back(i);
        dfs(1, 1);
        rep(i, 1, n) {
            if((md - d[i]) & 1) c1 ++;
            else c0 ++, c[a[i]] ++, ret ^= a[i];
        }
        if(ret) {
            rep(i, 1, n)
                if(((md - d[i]) & 1) && (ret ^ a[i]) <= 10000000) 
                    ans += c[ret ^ a[i]];
        }
        else {
            ans = c0 * (c0 - 1) + c1 * (c1 - 1), ans >>= 1;
            rep(i, 1, n)
                if((md - d[i]) & 1) 
                    ans += c[a[i]];
        }
        cout << ans;
        return 0;
    }
    View Code
  • 相关阅读:
    算法初步——哈希表B.1038统计同成绩学生
    算法初步——哈希表B10133.旧键盘打字 (注意bool型数组的赋值为true的方法)
    算法初步——哈希表B1029/A1084. 旧键盘
    算法初步——排序 A1012.The Best Rank(25)
    《思维导图》——东尼博赞
    算法初步——排序B1015/A1062.德才论
    入门模拟——(字符串处理)A1001. A+B Format(20)
    RMQ问题(线段树+ST算法)
    PKU 2406 Power Strings(KMP最长循环不重叠字串)
    KMP算法 kuangbin
  • 原文地址:https://www.cnblogs.com/ytytzzz/p/6932711.html
Copyright © 2011-2022 走看看