zoukankan      html  css  js  c++  java
  • Codeforces Round #663 题解

    Problem A. Suborrays

    笔者的直觉告诉自己,构造一个单峰的排列即可,但没想到任何排列都满足情况。

    时间复杂度 (mathcal O(n))

    #include <cstdio>
    #include <vector>
    
    using namespace std;
    
    int main() {
      int t;
      scanf("%d", &t);
      while (t--) {
        int n;
        scanf("%d", &n);
        int cnt = 1; 
        vector<int> ans; 
        for (; cnt <= n; cnt += 2) ans.push_back(cnt);
        cnt -= 2; 
        if (cnt + 1 == n) 
          ++cnt;
        else 
          --cnt; 
        for (; cnt >= 1; cnt -= 2) ans.push_back(cnt);
        for (auto i : ans) printf("%d ", i);
        puts("");
      }
      return 0; 
    }
    

    Problem B. Fix You

    因为每一个格子只会有 (R) 或者 (D),那么显然不合法的情况只存在于靠在边界,并且连着外面的情况。

    时间复杂度 (mathcal O(nm))

    #include <cstdio>
    
    using namespace std;
    
    int main() {
      int t;
      scanf("%d", &t);
      while (t--) {
        int n, m, ans = 0; 
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) {
          char s[m + 1];
          scanf("%s", s); 
          for (int j = 0; j < m; ++j) {
            if (s[j] == 'D' && i == n) 
              ++ans;
            if (s[j] == 'R' && j == m - 1) 
              ++ans; 
          }
        }
        printf("%d
    ", ans);
      }
      return 0; 
    }
    

    Problem C. Cyclic Permutations

    考虑合法方案的构造方法。

    排列内部一定存在 ({a,b,c}) 这样一个子序列,满足 (ble a,c) 的情况。

    所以答案为 (n!-2^{n-1}),其中 (2^{n-1}) 为所有数放到一边的情况。

    时间复杂度 (mathcal O(n))

    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    
    const int P = 1e9 + 7;
    
    int main() {
      int n; 
      scanf("%d", &n);
      int ans = 1, t = 1; 
      for (int i = 1; i <= n; ++i) ans = (ll)ans * i % P; 
      for (int i = 1; i < n; ++i) t = (ll)t * 2 % P; 
      printf("%d
    ", (ans - t + P) % P);
      return 0;
    }
    

    Problem D. 505

    显然不可能存在 (4 imes 4) 及以上的子矩阵,因为 (4) 个奇数的和为偶数,那么行数就 (leq 3)

    考虑状压 DP,令 (f[i][j]) 表示前 (i) 列合法,且第 (i) 列的状态为 (j) 的最少修改次数。

    [f[i+1][mask]=Min{f[i][j]+fix(mask)} ]

    其中 (fix(mask)) 是将原矩阵的状态修改成 (mask) 的修改次数。

    时间复杂度 (mathcal O(m imes 2^{2n}))

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    template <class T> 
    void chkmax(T& x, T y) { x = x > y ? x : y; }
    
    template <class T>
    void chkmin(T& x, T y) { x = x < y ? x : y; }
    
    int n, m;
    vector<string> s;
    
    int calc(int mask, int j) {
      int res = 0; 
      for (int i = 0; i < n; ++i) 
        if ((mask >> i & 1) != (s[i][j] - '0')) 
          ++res; 
      return res; 
    }
    
    bool check(int a, int b) {
      for (int i = 0; i < n - 1; ++i) 
        if (((a >> i & 1) + (a >> i + 1 & 1) + (b >> i & 1) + (b >> i + 1 & 1)) % 2 == 0) 
          return 0; 
      return 1; 
    }
    
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.tie(nullptr); 
      cin >> n >> m; 
      if (n >= 4) {
        cout << -1 << '
    ';
        return 0; 
      }
      s.resize(n); 
      for (int i = 0; i < n; ++i) cin >> s[i];
      vector<vector<int>> dp(m, vector<int>(1 << n, 1e9)); 
      for (int mask = 0; mask < 1 << n; ++mask) dp[0][mask] = calc(mask, 0);
      for (int i = 0; i < m - 1; ++i) 
        for (int c_mask = 0; c_mask < 1 << n; ++c_mask) 
          for (int n_mask = 0; n_mask < 1 << n; ++n_mask) 
            if (check(c_mask, n_mask)) 
              chkmin(dp[i + 1][n_mask], dp[i][c_mask] + calc(n_mask, i + 1));
      int ans = 1e9; 
      for (int mask = 0; mask < 1 << n; ++mask) chkmin(ans, dp[m - 1][mask]); 
      cout << ans << '
    ';
      return 0;
    }
    

    Problem E. Pairs of Pairs

    Task 1 的做法就只需要找到深度最深的一个节点并判断即可。

    Task 2 我们考虑 dfs 后对于深度相同的节点进行配对。

    对于同一深度的点对配对一定不存在导出子图的边,而深度差 (1) 的点对配对最多存在 (2) 条导出子图上的边。

    时间复杂度 (O(n))

    #include <cstdio>
    #include <vector>
    #include <functional>
    
    using namespace std;
    
    int main() {
      int t;
      scanf("%d", &t);
      while (t--) {
        int n, m;
        scanf("%d %d", &n, &m);
        vector<vector<int>> g(n); 
        for (int i = 0; i < m; ++i) {
          int u, v; 
          scanf("%d %d", &u, &v);
          --u, --v;
          g[u].push_back(v);
          g[v].push_back(u);
        }
        vector<int> dep(n), fa(n); 
        int max_dep = 0;
        function<void(int u, int fa)> dfs = [&](int u, int fp) {
          dep[u] = dep[fp] + 1; 
          fa[u] = fp; 
          if (dep[u] > dep[max_dep]) 
            max_dep = u; 
          for (auto v : g[u]) 
            if (!dep[v]) 
              dfs(v, u); 
        };
        dfs(0, 0); 
        if (dep[max_dep] >= (n + 1) / 2) {
          printf("PATH
    %d
    ", dep[max_dep]); 
          int u = max_dep; 
          do 
            printf("%d ", u + 1); 
          while (u = fa[u]); 
          printf("1"); 
        } else {
          printf("PAIRING
    "); 
          vector<vector<int>> dp(dep[max_dep]); 
          for (int i = 0; i < n; ++i) dp[dep[i] - 1].push_back(i);
          int ans = 0; 
          for (int i = 0; i < dep[max_dep]; ++i) ans += (dp[i].size() >> 1); 
          printf("%d
    ", ans); 
          for (int cur_dep = 0; cur_dep < dep[max_dep]; ++cur_dep) 
            for (unsigned i = 0; i < dp[cur_dep].size() - 1; i += 2) printf("%d %d
    ", dp[cur_dep][i] + 1, dp[cur_dep][i + 1] + 1); 
        }
        puts(""); 
      }
      return 0; 
    }
    
  • 相关阅读:
    曲面的外在几何(一)---曲面的基本理论
    几个积性函数的均值
    多重小数部分和的渐近式与小数部分积分(Ⅱ)
    二重小数部分和的渐近式
    一个极限问题
    正整数互素的概率问题
    多重小数部分和的渐近式与Ovidiu Furdui积分问题
    $prodlimits_{substack{(k,n)=1 \ 1leqslant k leqslant n}} k$ 的阶
    2016 年中国科学院大学数学分析考研试题
    无平方因子数的分布 (Ⅰ)
  • 原文地址:https://www.cnblogs.com/chhokmah/p/13498959.html
Copyright © 2011-2022 走看看