• Codeforces Round #455 (Div. 2)


    C. Python Indentation

    分析

    (dp[i][j]) 表示到第 (i) 行时,缩进次数为 (j) 的方案数。

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int MOD = 1e9 + 7;
    string c;
    long long dp[5555][5555];
    int main() {
        int n;
        cin >> n;
        dp[0][0] = 1;
        for (int i = 0; i < n; i++) {
            cin >> c;
            if(c == "f") {
                for (int j = 1; j < n; j++) {
                    dp[i + 1][j] = dp[i][j - 1];
                }
            } else {
                for (int j = n; j >= 0; j--) {
                    dp[i + 1][j] = (dp[i][j] + dp[i + 1][j + 1]) % MOD;
                }
            }
        }
        cout << dp[n][0] << endl; 
        return 0;
    }
    

    D. Colorful Points

    分析

    将字符串按字符分组,记录字符和连续相同的字符个数,那么每次删掉的字符应该是,左右两边的组中的一个字符,中间每组两个字符 ,将空组删掉,合并可以合并的组。模拟一下就行了,因为对于每组每回合至少会删掉一个字符,复杂度 (O(n))

    code

    #include<bits/stdc++.h>
    using namespace std;
    string s;
    vector<pair<char, int> > v, tmp;
    int main() {
        cin >> s;
        int len = s.length();
        v.push_back(pair<int, int>(s[0], 1));
        for (int i = 1; i < len; i++) {
            if(s[i] == v.back().first) {
                v[v.size() - 1].second++;
            } else {
                v.push_back(pair<int, int>(s[i], 1));
            }
        }
        int ans = 0;
        while(v.size() > 1) {
            ans++;
            for (int i = 0; i < v.size(); i++) {
                if(!i) {
                    if(v[i].second - 1 > 0) {
                        v[i].second--;
                        tmp.push_back(v[i]);
                    }
                } else if(i == v.size() - 1) {
                    if(v[i].second - 1 > 0) {
                        v[i].second--;
                        if(!tmp.empty() && tmp.back().first == v[i].first) {
                            tmp[tmp.size() - 1].second += v[i].second;
                        } else {
                            tmp.push_back(v[i]);
                        }
                    }
                } else {
                    if(v[i].second - 2 > 0) {
                        v[i].second -= 2;
                        if(!tmp.empty() && tmp.back().first == v[i].first) {
                            tmp[tmp.size() - 1].second += v[i].second;
                        } else {
                            tmp.push_back(v[i]);
                        }   
                    }
                }
            }
            v = tmp;
            tmp.clear();
        }
        cout << ans << endl;
        return 0;
    }
    

    E. Coprocessor

    分析

    与前面两题相比感觉这道题反而没什么技巧。

    找入度为 0 的点,分类存储,遍历再去 DFS 更新其它点的入度,重复这样即可。

    code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    vector<int> G[N];
    int c[N], d[N];
    vector<int> v0, v1;
    
    void dfs(int flg, int u) {
        for (int v : G[u]) {
            d[v]--;
            if (!d[v]) {
                if (c[v]) {
                    if (flg)
                        dfs(flg, v);
                    else
                        v1.push_back(v);
                } else {
                    if (flg)
                        v0.push_back(v);
                    else
                        dfs(flg, v);
                }
            }
        }
    }
    
    int main() {
        int n, m;
        cin >> n >> m;
        for (int i = 0; i < n; i++) {
            cin >> c[i];
        }
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            G[v].push_back(u);
            d[u]++;
        }
        for (int i = 0; i < n; i++) {
            if (!d[i]) {
                c[i] ? v1.push_back(i) : v0.push_back(i);
            }
        }
        int ans = 0;
        while (!v0.empty() || !v1.empty()) {
            for (int u : v0) {
                dfs(0, u);
            }
            v0.clear();
            if (!v1.empty()) ans++;
            for (int u : v1) {
                dfs(1, u);
            }
            v1.clear();
        }
        cout << ans << endl;
        return 0;
    }
    

    F. AND-permutations

    分析

    构造题。

    对二进制和位运算还是不够敏感啊。

    对于第一个问题,要求排列后每个数都不在原来的位置,且与位置序号数按位与运算后都为 0 。

    对于奇数情况,无解,因为奇数情况下所有数表示成二进制后,末尾为 (1) 的数个数一定比为 (0) 的多 (1) ,所以无论如何,都会存在一个对应情况按位与后末尾为 (1)

    对于偶数情况,只需要注意到一个事实:

    (n=2^k)(m=2^k-1)((n+i)&(m-i)=0(m geq i)) ,因为此时 (n) 除了前导 (1) 全是 (0)(m) 除了前导 (0) 以外全是 (1) ,那么可以想象成这些 (1) 全都可以加到 (n) 上去。

    举个例子,若 (n=12),我们找到小于等于 (n) 的最大的 (2) 的倍数 (8) ,那么 ((7,8) (6,9) (5,10) (4,11) (3,12)) 对应,然后 (n=2),我们找到小于等于 (n) 的最大的 (2) 的倍数 (2)((1,2)) 对应,(n=0) 后可以发现所有数都有对应关系了。因为起始 (n) 是偶数,且每次减去的数一定是偶数,且 (n) 一定不会减到小于 (0),所以一定能构造出答案。

    对于第二个问题,按位运算后都不为 (0)

    如果 (n)(2) 的倍数,则无解,因为没有数可以和 (n) 对应。

    对于 (n<8) 的情况要特判。

    对于 (ngeq 8) 的情况,考虑 ([8,15] [16, 31]...),对于每个区间单独考虑,转化成二进制数后每个数的首位数一定都为 (1) ,只要保证每个数都不在原来的位置即可。

    code

    #include <bits/stdc++.h>
    using namespace std;
    
    int p2(int x) {
        int a = 1;
        while (a * 2 <= x) {
            a *= 2;
        }
        return a;
    }
    
    int ans[111111];
    
    int main() {
        int n;
        cin >> n;
        if (n & 1) {
            cout << "NO
    ";
        } else {
            cout << "YES
    ";
            int m = n;
            while (m) {
                int x = p2(m);
                for (int i = x, j = x - 1; i <= m; i++, j--) { ans[i] = j; ans[j] = i; }
                m -= 2 * (m - x + 1);
            }
            for (int i = 1; i <= n; i++) {
                cout << ans[i] << " 
    "[i == n];
            }
        }
        if (n <= 5 || p2(n) == n)
            cout << "NO
    ";
        else {
            cout << "YES
    ";
            if (n == 6)
                cout << "3 6 2 5 1 4
    ";
            else if (n == 7)
                cout << "7 3 6 5 1 2 4
    ";
            else {
                cout << "7 3 6 5 1 2 4";
                int l = 8;
                while (l <= n) {
                    int r = min(n, l * 2 - 1);
                    for (int i = l + 1; i <= r; i++) {
                        cout << " " << i;
                    }
                    cout << " " << l;
                    l = r + 1;
                }
                cout << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    mysql学习日志
    Python学习day10 Javascript/Jquery
    Python学习day07 多线程多进程及主机管理
    Linux基本命令
    django 用户认证/Excel导入Mysql
    转:iptables详解
    Python django前端导入Excel脚本
    Python学习day08 分布式监控系统开发实战
    Subline Text2
    MySQL 常用函数分析
  • 原文地址:https://www.cnblogs.com/ftae/p/8385144.html
Copyright © 2020-2023  润新知