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

    A - Stones

    题意:有3堆石头a个,b个,c个,可以每次拿1个a堆的,2个b堆的,或者拿1个b堆的,2个c堆的。

    题解:b堆是唯一的公共资源,考虑尽可能充分利用b堆。每2个b堆的参与操作2可以得6个,参与操作1只能得3个,而且参与操作2只需要b堆还剩下一个就可以执行,所以先做操作2。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int main() {
    #ifdef KisekiPurin
        freopen("KisekiPurin.in", "r", stdin);
    #endif // KisekiPurin
        int t;
        scanf("%d", &t);
        while(t--) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            int n1 = min(b, c / 2);
            b -= n1;
            int n2 = min(a, b / 2);
            printf("%d
    ", 3 * (n1 + n2));
        }
        return 0;
    }
    

    B - Alice and the List of Presents

    题意:有n种礼物,m个盒子。每个盒子每种礼物个至多一个。每种礼物总共至少放一个。求方案数。

    题解:把每种礼物不放的那种去除。每个盒子放和不放有两种,每种礼物有2^m-1种,全部乘起来。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int mod = 1e9 + 7;
    
    ll pow_mod(ll x, int n) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % mod;
            x = x * x % mod;
            n >>= 1;
        }
        return res;
    }
    
    int main() {
    #ifdef KisekiPurin
        freopen("KisekiPurin.in", "r", stdin);
    #endif // KisekiPurin
        int n, m;
        scanf("%d%d", &n, &m);
        printf("%lld
    ", pow_mod(pow_mod(2, m) - 1, n));
    }
    

    C - Labs

    题意:有n*n个数,均分成n组,每个大数向小数连一条流量为1的边。组X与组Y间的单向流量就是X的每个元素流给Y的每个元素的和。分配这些元素使得流量的最小值最大。

    题解:流量的最小值最大意思就是尽可能平均分配的意思。一开始以为是

    1 4 7
    2 5 8
    3 6 9
    

    这样分配,但很显然是不对的,居然还给交了一发。

    这种题可以考虑模仿样例的做法,给样例排序,变成:

    1 6 7
    2 5 8
    3 4 9
    

    是个蛇形填数?为什么蛇形填数是最平均的呢?我们考虑只有偶数列的情况(n为偶数的情况),每相邻两列内部的流量都是2,而与其他列的流量都相等。但奇数的话会始终多1列出来没有办法解决。而可以证明出已经达到了最优解(把所有的流量均分n份的最小值已经达到)。

    所以写个蛇形填数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int g[305][305];
    
    int main() {
    #ifdef KisekiPurin
        freopen("KisekiPurin.in", "r", stdin);
    #endif // KisekiPurin
        int n;
        scanf("%d", &n);
        int cnt = 0, i = 1, j = 1, di = 1, dj = 0;
        while(cnt < n * n) {
            g[i][j] = ++cnt;
            i += di;
            j += dj;
            if(i == n && di == 1) {
                di = 0;
                dj = 1;
            } else if(i == n && dj == 1) {
                di = -1;
                dj = 0;
            } else if(i == 1 && di == -1) {
                di = 0;
                dj = 1;
            } else if(i == 1 && dj == 1) {
                di = 1;
                dj = 0;
            }
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                printf("%d%c", g[i][j], " 
    "[j == n]);
            }
        }
    }
    

    D - Alice and the Doll

    题意:一个n*m格子矩阵,放一个人偶在左上角向右走,只能在每个格子最多右转一次,有k个障碍物。求是否能够一次走完矩阵的所有非障碍物格然后停留在任意位置。

    题解:在每个格子最多右转一次,相当于每个格子只能走一次,否则就出不来了。容易想到障碍物必须也是占据一些蛇形的片段,并且留下的位置刚好可以让人偶走一个蛇形的绕到中心,但是怎么判断障碍物的形状呢?百思不得其解遂看题解。题解表示观察到人偶撞墙或者撞障碍物必转向(自己走过的路也是墙)。然后暴力模拟一遍,每次在数据结构里面搜索前进方向上最近的墙/障碍物,走到它面前。至多进行n+m次。

    所以选择一个结构就是set,维护行和列分别两堆set,一个障碍物同时插入行列两个set里面。然后墙/自己走过形成的墙就设置一个最值把多走的部分截断就可以了。判断答案的方法就是暴力统计走过的格子数是否等于空格数。

    注:实现的时候卡在了样例4,因为会让人偶走回头路,但是也不能够简单让人偶移动0格就退出,比如一条竖线的矩阵。修复的方法是在人偶的后方一个格子塞一个障碍物。然后卡在样例9,看了dalao的代码才知道错在哪里,首先while循环的停止条件错了,不应该是d>u||r>l,应该是d>=u&&r>=l,因为是闭区间。这个改进再加上后面堵一个障碍物就可以防止原路返回了,人偶会在中间不断转圈圈。不过最简单的办法是记录人偶原地不动的次数,>=2次就break掉。

    其实并不需要堵格子,记录原地不动的次数之后就不会原路返回了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
     
    set<int> sr[100005], sc[100005];
     
    int main() {
    #ifdef KisekiPurin
        freopen("KisekiPurin.in", "r", stdin);
    #endif // KisekiPurin
        int n, m, k;
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= n; ++i) {
            sr[i].insert(0);
            sr[i].insert(m + 1);
        }
        for(int i = 1; i <= m; ++i) {
            sc[i].insert(0);
            sc[i].insert(n + 1);
        }
        for(int i = 1; i <= k; ++i) {
            int r, c;
            scanf("%d%d", &r, &c);
            sr[r].insert(c);
            sc[c].insert(r);
        }
     
        int u = 1, d = n, l = 1, r = m;
        int x = 1, y = 1, dir = 1, stay = 0;
        ll cnt = 1;
        while(d >= u && r >= l) {
            if(dir == 1) {
                int ny = min(r, *sr[x].upper_bound(y) - 1);
                cnt += ny - y;
                if(ny == y) {
                    if(stay == 0)
                        stay = 1;
                    else
                        break;
                } else
                    stay = 0;
                y = ny;
                ++u;
                r = y;
                dir = 2;
            } else if(dir == 2) {
                int nx = min(d, *sc[y].upper_bound(x) - 1);
                cnt += nx - x;
                if(nx == x) {
                    if(stay == 0)
                        stay = 1;
                    else
                        break;
                } else
                    stay = 0;
                x = nx;
                --r;
                d = x;
                dir = 3;
            } else if(dir == 3) {
                int ny = max(l, *(--(sr[x].lower_bound(y))) + 1);
                cnt += y - ny;
                if(ny == y) {
                    if(stay == 0)
                        stay = 1;
                    else
                        break;
                } else
                    stay = 0;
                y = ny;
                --d;
                l = y;
                dir = 4;
            } else {
                int nx = max(u, *(--(sc[y].lower_bound(x))) + 1);
                cnt += x - nx;
                if(nx == x) {
                    if(stay == 0)
                        stay = 1;
                    else
                        break;
                } else
                    stay = 0;
                x = nx;
                ++l;
                u = x;
                dir = 1;
            }
        }
        puts((cnt == 1ll * n * m - k) ? "YES" : "NO");
    }
    
  • 相关阅读:
    JS判断对象中是否存在某参数
    JS通过url下载文件
    .NET CORE LinQ查询中计算时间差
    C# 判断某个时间是星期几
    C#数组去重
    python Tank
    kubeflannel.yml Tank
    片言只语 Tank
    other Tank
    ERROR大集合 Tank
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/11853103.html
Copyright © 2011-2022 走看看