zoukankan      html  css  js  c++  java
  • Codeforces Global Round 6

    好演啊,完蛋了,只会ABC。

    关注的人不够多,假如有榜看的话估计可以发现D是简单题来的,多关注几个红名爷好了。

    首先A就想复杂了一开始就应该往质因数分解那里想。

    B看了图也想复杂了,观察一下很显然。

    C看错题太演了,单行单列要小心一点。

    D应该先看榜的,比赛不是乱做,应该看榜,前面一圈人秒杀D,D就不应该是复杂的图,又消环又干嘛的。

    A - Competitive Programme

    题意:给一个字符串,对它重新排列使得它是60的倍数。

    题解:首先这个是A题,在CF中要坚信它是水题。60的倍数一定是10的倍数所以必须有至少一个0,先把没有0的去掉。然后去掉其中一个0。然后要求是6的倍数,3的倍数满足十进制数位和都是3,2的倍数要求以2结尾,分别判断就可以了。

    char s[1005];
     
    void test_case() {
        scanf("%s", s + 1);
        int l = strlen(s + 1);
        int sum = 0;
        for(int i = 1; i <= l; ++i)
            sum += s[i] - '0';
        /*不是3的倍数*/
        if(sum % 3 != 0) {
            puts("cyan");
            return;
        }
        /*150*/
        int cnt0 = 0, cnt2 = 0, cntn0 = 0;
        for(int i = 1; i <= l; ++i) {
            if(s[i] == '0')
                ++cnt0;
            else
                ++cntn0;
            if((s[i] - '0') % 2 == 0)
                ++cnt2;
        }
        /*全是0*/
        if(cntn0 == 0) {
            puts("red");
            return;
        }
        /*没有0*/
        if(cnt0 == 0) {
            puts("cyan");
            return;
        }
        /*有0,也有至少两个偶数,0提供1个2和5,另一个提供另一个2*/
        if(cnt2 >= 2) {
            puts("red");
            return;
        }
        puts("cyan");
        return;
    }
    

    B - Dice Tower

    题意:给一个数,问他是不是可以由一个骰子塔的所有接触空气的面的数字构成。

    题解:123456轮流朝下有[15,20]6种不同的结果。而骰子的对面的和永远都是7,所以骰子塔的中间不管怎么摆都是+14每层。

    void test_case() {
        /*最小的肯定是12345=15*/
        /*12346=16*/
        /*12356=17*/
        /*12456=18*/
        /*13456=19*/
        /*23456=20*/
        /*然后必须加一层,加一层最小的,注意骰子对面都是7,所以没最小的,都是+14*/
        ll x;
        scanf("%lld", &x);
        if(x <= 14) {
            puts("NO");
            return;
        }
        x %= 14;
        if(x >= 1 && x <= 6) {
            puts("YES");
            return;
        }
        puts("NO");
        return;
    }
    

    C - Diverse Matrix

    题意:往一个矩阵里面填数,使得每行每列的gcd都两两各不相同。且最大的gcd最小。

    题解:一开始没看见“且最大的gcd最小”,就随便掏了一群质数瞎乘上去。改了之后就发现其实是要用连续的自然数,首先给第一行安排一堆连续的自然数那么他们的gcd肯定就是1,然后在下面给他们一起乘上多少倍他们的gcd就是多少。注意只有1或1列的情况不能出现数字1,其他的情况是可以出现的。无论如何都是刚好从1开始到r+c的。

    int a[505][505];
     
    void test_case() {
        int r, c;
        scanf("%d%d", &r, &c);
        if(r == 1 && c == 1) {
            puts("0");
            return;
        }
        if(r == 1) {
            for(int j = 1; j <= c; ++j)
                a[1][j] = j + 1;
            for(int i = 1; i <= r; ++i) {
                for(int j = 1; j <= c; ++j)
                    printf("%d%c", a[i][j], " 
    "[j == c]);
            }
            return;
        }
        if(c == 1) {
            for(int i = 1; i <= r; ++i)
                a[i][1] = i + 1;
            for(int i = 1; i <= r; ++i) {
                for(int j = 1; j <= c; ++j)
                    printf("%d%c", a[i][j], " 
    "[j == c]);
            }
            return;
        }
        for(int i = 1; i <= r; ++i) {
            for(int j = 1; j <= c; ++j)
                a[i][j] = 1;
        }
        int curp = 0;
        for(int i = 1; i <= r; ++i) {
            int P = ++curp;
            for(int j = 1; j <= c; ++j)
                a[i][j] *= P;
        }
     
        for(int j = 1; j <= c; ++j) {
            int P = ++curp;
            for(int i = 1; i <= r; ++i)
                a[i][j] *= P;
        }
     
        for(int i = 1; i <= r; ++i) {
            for(int j = 1; j <= c; ++j)
                printf("%d%c", a[i][j], " 
    "[j == c]);
        }
        return;
    }
    

    D - Decreasing Debts

    题意:有n个人,m条借钱关系,你可以按照常识来简化借钱关系进行等价变换,使得总的借钱数额最小。

    题解:消环DAG确实可以,这波亏一半,写起来有一些细节错了,没事下次就可以了。其实看分值这题就不应该这么做。这样写的细节难度至少有C的3倍。

    vector<pii> PG1[200005];
    
    void AddEdge1(int u, int v, int w) {
        if(u == v || w == 0)
            return;
        if(!PG1[v].empty()) {
            pii tmp = PG1[v].back();
            PG1[v].pop_back();
            int t = tmp.second;
            if(t == u) {
                if(w >= tmp.first) {
                    AddEdge1(u, v, w - tmp.first);
                    return;
                } else {
                    AddEdge1(v, u, tmp.first - w);
                    return;
                }
            }
            if(w >= tmp.first) {
                AddEdge1(u, t, tmp.first);
                AddEdge1(u, v, w - tmp.first);
                return;
            } else {
                AddEdge1(u, t, w);
                AddEdge1(v, t, tmp.first - w);
                return;
            }
        }
        if(w)
            PG1[u].push_back({w, v});
    }
    
    vector<pii> PG2[200005];
    
    void AddEdge2(int u, int v, int w) {
        if(u == v || w == 0)
            return;
        if(!PG2[v].empty()) {
            pii tmp = PG2[v].back();
            PG2[v].pop_back();
            int t = tmp.second;
            if(t == u) {
                if(w >= tmp.first) {
                    AddEdge2(u, v, w - tmp.first);
                    return;
                } else {
                    AddEdge2(v, u, tmp.first - w);
                    return;
                }
            }
            if(w >= tmp.first) {
                AddEdge2(u, t, tmp.first);
                AddEdge2(u, v, w - tmp.first);
                return;
            } else {
                AddEdge2(u, t, w);
                AddEdge2(v, t, tmp.first - w);
                return;
            }
        }
        if(w)
            PG2[u].push_back({w, v});
    }
    
    vector<pii> G[200005];
    vector<int> AG[200005];
    queue<int> Q;
    
    int outdeg[200005];
    
    map<int, ll> MG[200005];
    
    void test_case() {
        int n, m;
        scanf("%d%d", &n, &m);
        while(m--) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            AddEdge1(u, v, w);
        }
        for(int i = 1; i <= n; ++i) {
            while(!PG1[i].empty()) {
                pii tmp = PG1[i].back();
                PG1[i].pop_back();
                int v = tmp.second, w = tmp.first;
                G[i].push_back({v, w});
                AG[v].push_back(i);
            }
        }
        for(int i = 1; i <= n; ++i) {
            outdeg[i] = G[i].size();
            if(outdeg[i] == 0)
                Q.push(i);
        }
        while(!Q.empty()) {
            int u = Q.front();
            Q.pop();
            for(auto &e : G[u])
                AddEdge2(u, e.first, e.second);
            for(auto &v : AG[u]) {
                --outdeg[v];
                if(outdeg[v] == 0)
                    Q.push(v);
            }
        }
        for(int i = 1; i <= n; ++i) {
            while(!PG2[i].empty()) {
                pii tmp = PG2[i].back();
                PG2[i].pop_back();
                int u = i, w = tmp.first, v = tmp.second;
                MG[u][v] += w;
            }
        }
        int sum = 0;
        for(int i = 1; i <= n; ++i)
            sum += MG[i].size();
        printf("%d
    ", sum);
        for(int i = 1; i <= n; ++i) {
            for(auto &e : MG[i])
                printf("%d %d %lld
    ", i, e.first, e.second);
        }
    }
    

    这东西的复杂度怎么证明啊?会不会本身就是一个假算法?

    题解:事实上每个人只需要关心他实际借出/借入了多少钱,对象是无所谓的,随便找个人填上去就可以了。

    ll sum[200005];
    vector<int>P, N;
    
    map<int, ll> MG[200005];
    
    void test_case() {
        int n, m;
        scanf("%d%d", &n, &m);
        while(m--) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            sum[u] += w;
            sum[v] -= w;
        }
        for(int i = 1; i <= n; ++i) {
            if(sum[i] < 0)
                N.push_back(i);
            else if(sum[i] > 0)
                P.push_back(i);
        }
    
        while(!P.empty()) {
            int u = P.back();
            P.pop_back();
            int v = N.back();
            N.pop_back();
            ll d = min(sum[u], -sum[v]);
            sum[u] -= d;
            sum[v] += d;
            MG[u][v] += d;
            if(sum[u])
                P.push_back(u);
            if(sum[v])
                N.push_back(v);
        }
    
        int sum = 0;
        for(int i = 1; i <= n; ++i)
            sum += MG[i].size();
        printf("%d
    ", sum);
        for(int i = 1; i <= n; ++i) {
            for(auto &e : MG[i])
                printf("%d %d %lld
    ", i, e.first, e.second);
        }
    }
    

    E - Spaceship Solitaire

    题意:建造一艘太空船,需要n种资源,第i种资源的需求是ai。每次加入/改变/删除一个任务奖励,达成该任务就获得一个奖励的资源,在每次操作后输出当前需要的资源数,注意每种资源的每个进度的奖励资源至多只有1个。

    题解:一开始就是ai的和,然后加入一个必定会减少1。再继续加入的话要判断当前奖励的是否已经饱和,饱和的话就不再改变。反过来想的确是显然的,但是正向怎么构造呢?

    int n, q, a[200005], b[200005];
    map<int, int> M[200005];
    ll sum;
    
    void Sub(int u) {
        if(u) {
            --b[u];
            if(b[u] < a[u])
                ++sum;
        }
    }
    
    void Add(int u) {
        if(u) {
            ++b[u];
            if(b[u] <= a[u])
                --sum;
        }
    }
    
    void test_case() {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            sum += a[i];
        }
        scanf("%d", &q);
        while(q--) {
            int s, t, u;
            scanf("%d%d%d", &s, &t, &u);
            Sub(M[s][t]);
            Add(u);
            M[s][t] = u;
            printf("%lld
    ", sum);
        }
    }
    
  • 相关阅读:
    2.App Components-Activities/Loadres
    2.App Components-Activities/Fragments
    2.App Components-Activities
    2.App Components-Intents and Intent Filters
    1.Indroduction
    Fragment
    用继承和组合方式定制控件
    复杂布局实现
    Android源代码下载与跟踪
    电梯调度算法模拟
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12057840.html
Copyright © 2011-2022 走看看