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

    Codeforces Round #558 (Div. 2) 题解

    A Eating Soup

    分类讨论一下

    (m) 个断点最多可以将环分成 (m) 段,而剩下 (n-m) 个点最多可以成为 (n-m) 段,取个 (min) 即可

    注意 (m=0) 时是一个环答案为 (1)

    // Copyright lzt
    #include<stdio.h>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<string>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    typedef std::pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef std::pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read() {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
      }
      while (ch <= '9' && ch >= '0') {
        x = 10 * x + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    
    int n, m;
    
    void work() {
      n = read(), m = read();
      if (m == 0) {
        puts("1");
        return;
      }
      int num = n - m;
      printf("%d
    ", min(num, m));
    }
    
    int main() {
      #ifdef LZT
        freopen("in", "r", stdin);
      #endif
    
      work();
    
      #ifdef LZT
        Debug("My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
      #endif
    }
    

    B Cat Party

    倒着枚举长度并且维护每一个出现次数的个数

    就是维护出现次数为 (i) 的数字有多少个

    显然出现次数最多只能有两种(因为你只能修改 (1) 个数,也就只能修改一个出现次数)

    然后就分类讨论一下最后删掉的是哪个即可

    // Copyright lzt
    #include<stdio.h>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<string>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    typedef std::pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef std::pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read() {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
      }
      while (ch <= '9' && ch >= '0') {
        x = 10 * x + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    
    const int maxn = 100100;
    int n, cnt;
    int a[maxn];
    int b[maxn], num[maxn];
    
    void work() {
      n = read();
      rep(i, 1, n) a[i] = read(), b[a[i]]++;
      cnt = 0; set<int> col;
      rep(i, 1, 100000) {
        if (b[i]) {
          num[b[i]]++;
          cnt++, col.insert(b[i]);
        }
      }
      rrep(i, n, 2) {
        int nw = *col.begin();
        if (num[nw] == 1 && col.size() > 1) nw = *(++col.begin());
        if (col.size() <= 2) {
          bool ok = 0;
          if (col.size() == 1) {
            int nw = *col.begin();
            if (nw == 1 || num[nw] == 1) ok = 1;
            else ok = 0;
          } else {
            int A = *col.begin(), B = *(++col.begin());
            if (num[A] == 1 && A == 1) ok = 1;
            else if (num[B] == 1 && B == 1) ok = 1;
            else if (num[B] == 1 && B == A + 1) ok = 1;
            else ok = 0;
          }
          if (ok) {
            printf("%d
    ", i);
            return;
          }
        }
        num[b[a[i]]]--;
        if (num[b[a[i]]] == 0) col.erase(b[a[i]]);
        b[a[i]]--;
        if (b[a[i]]) {
          num[b[a[i]]]++;
          if (num[b[a[i]]] == 1) col.insert(b[a[i]]);
        }
        else cnt--;
      }
      puts("1");
    }
    
    int main() {
      #ifdef LZT
        freopen("in", "r", stdin);
      #endif
    
      work();
    
      #ifdef LZT
        Debug("My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
      #endif
    }
    

    C Power Transmission

    答案显然是 (calc( ext{不同的直线数量}) - sum_{ ext{斜率k}} calc( ext{斜率为k的直线数量}))

    其中 (calc(x)=x*(x-1)/2)

    然后就枚举每两个点形成一条线,然后计数即可

    // Copyright lzt
    #include<stdio.h>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<string>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    typedef std::pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef std::pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read() {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
      }
      while (ch <= '9' && ch >= '0') {
        x = 10 * x + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    
    const int maxn = 1010;
    int n;
    pii p[maxn];
    
    bool sm(double x, double y) {
      return fabs(x - y) <= 1e-8;
    }
    
    struct Line {
      // Ax + By + C = 0
      double A, B, C;
      bool operator == (const Line &b) const {
        return sm(A, b.A) && sm(B, b.B) && sm(C, b.C);
      }
      bool operator < (const Line &b) const {
        if (sm(A, b.A)) {
          if (sm(B, b.B)) return C < b.C;
          return B < b.B;
        }
        return A < b.A;
      }
      void init() {
        if (A == 0) C = C / B, B = 1;
        else B = B / A, C = C / A, A = 1;
      }
      double calc() {
        init();
        if (A == 1) return B;
        else return 1e30;
      }
    };
    
    map<double, map<double, int> > M;
    map<double, int> shit;
    vector<Line> v;
    
    void work() {
      n = read();
      rep(i, 1, n) p[i].fi = read(), p[i].se = read();
      ll num = 0;
      rep(i, 1, n) rep(j, i + 1, n) {
        Line nw;
        nw.A = p[j].se - p[i].se;
        nw.B = p[i].fi - p[j].fi;
        nw.C = 0 - p[i].fi * nw.A - p[i].se * nw.B;
        nw.init();
        double k = nw.calc();
        if (M[k][nw.C] == 0) {
          M[k][nw.C] = 1;
          num++; shit[k]++;
        }
      }
      num = num * (num - 1) / 2;
      for (map<double, int>::iterator it = shit.begin(); it != shit.end(); it++) {
        int nw = it -> se;
        num = num - nw * 1ll * (nw - 1) / 2;
      }
      printf("%lld
    ", num);
    }
    
    int main() {
      #ifdef LZT
        freopen("in", "r", stdin);
      #endif
    
      work();
    
      #ifdef LZT
        Debug("My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
      #endif
    }
    

    D Mysterious Code

    首先预处理 (S[i][j])(T[i][j]) 分别表示当前串的后缀与 (s/t) 的前缀的最长公共子串长度为 (i) (也就是只有最后 (i) 位有用,前面的都忽略),然后下一个位置填了字母 (j) 之后那个最长公共子串的长度(类似 (kmp)(fail)

    直接 (dp) (f[i][j][k]) 表示当前长度为 (i),在第一个串上的位置是 (j) ,在第二个串上的位置是 (k) 的最大 (f(c',s)-f(c',t))

    然后转移就暴力枚举一下下一个是啥

    // Copyright lzt
    #include<stdio.h>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<string>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    typedef std::pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef std::pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read() {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
      }
      while (ch <= '9' && ch >= '0') {
        x = 10 * x + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    
    const int maxn = 1010;
    int n, m, len;
    char s[maxn], t[maxn], c[maxn];
    int f[maxn][55][55];
    int S[55][26], T[55][26];
    
    inline void getmx(int &x, int y) {
      if (x < y) x = y;
    }
    
    void work() {
      scanf("%s", c + 1); len = strlen(c + 1);
      scanf("%s", s + 1); n = strlen(s + 1);
      rep(i, 0, n) rep(j, 0, 25) {
        int len = i + 1;
        rrep(k, min(len, n), 1) {
          bool flag = true;
          rep(_, 1, k - 1) if (s[i - k + _ + 1] != s[_]) {
            flag = false; break;
          }
          if (s[k] - 'a' != j) flag = false;
          if (flag) {
            S[i][j] = k;
            break;
          }
        }
        // cout<<i<<' '<<j<<' '<<S[i][j]<<endl;
      }
      scanf("%s", t + 1); m = strlen(t + 1);
      rep(i, 0, m) rep(j, 0, 25) {
        int len = i + 1;
        rrep(k, min(len, m), 1) {
          bool flag = true;
          rep(_, 1, k - 1) if (t[i - k + _ + 1] != t[_]) {
            flag = false; break;
          }
          if (t[k] - 'a' != j) flag = false;
          if (flag) {
            T[i][j] = k;
            break;
          }
        }
        // cout<<i<<' '<<j<<' '<<T[i][j]<<endl;
      }
      rep(i, 0, len) rep(j, 0, n) rep(k, 0, m) f[i][j][k] = -1e9;
      f[0][0][0] = 0;
      rep(i, 0, len - 1) rep(j, 0, n) rep(k, 0, m) {
        if (f[i][j][k] == -1e9) continue;
        if (c[i + 1] != '*') {
          int nw = c[i + 1] - 'a', pl = 0;
          if (S[j][nw] == n) pl++;
          if (T[k][nw] == m) pl--;
          getmx(f[i + 1][S[j][nw]][T[k][nw]], f[i][j][k] + pl);
        } else {
          rep(nw, 0, 25) {
            int pl = 0;
            if (S[j][nw] == n) pl++;
            if (T[k][nw] == m) pl--;
            getmx(f[i + 1][S[j][nw]][T[k][nw]], f[i][j][k] + pl);
          }
        }
      }
      int ans = -1e9;
      rep(j, 0, n) rep(k, 0, m) {
        getmx(ans, f[len][j][k]);
      }
      printf("%d
    ", ans);
    }
    
    int main() {
      #ifdef LZT
        freopen("in", "r", stdin);
      #endif
    
      work();
    
      #ifdef LZT
        Debug("My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
      #endif
    }
    

    E Magical Permutation

    // Copyright lzt
    #include<stdio.h>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<string>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    typedef std::pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef std::pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read() {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
      }
      while (ch <= '9' && ch >= '0') {
        x = 10 * x + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    
    const int maxn = 200200;
    int n, ans, pos;
    int a[maxn], lb[20];
    vector<int> vec;
    bool vis[maxn << 2];
    
    void add(int v) {
      int tmp = v;
      rrep(i, 20, 0) {
        if (v & (1 << i)) {
          if (lb[i]) v ^= lb[i];
          else {
            vec.pb(tmp);
            lb[i] = v;
            break;
          }
        }
      }
    }
    
    void dfs(int v, int num) {
      printf("%d ", v); vis[v] = 1;
      if (num == (1 << ans)) return;
      rep(i, 0, vec.size() - 1) if (!vis[v ^ vec[i]]) {
        dfs(v ^ vec[i], num + 1);
        break;
      }
    }
    
    void work() {
      n = read();
      rep(i, 1, n) a[i] = read();
      sort(a + 1, a + n + 1);
      ans = 0, pos = 1;
      rep(i, 1, 20) {
        while (pos <= n && a[pos] < (1 << i)) {
          add(a[pos]);
          pos++;
        }
        bool flag = true;
        rep(j, 0, i - 1) if (!lb[j]) flag = false;
        if (flag) ans = i;
      }
      memset(lb, 0, sizeof(lb));
      vec.clear();
      rep(i, 1, n) {
        if (a[i] < (1 << ans)) add(a[i]);
      }
      printf("%d
    ", ans);
      dfs(0, 1);
    }
    
    int main() {
      #ifdef LZT
        freopen("in", "r", stdin);
      #endif
    
      work();
    
      #ifdef LZT
        Debug("My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
      #endif
    }
    
    
  • 相关阅读:
    Java编程思想读书笔记 第十章 内部类
    利用lambda和条件表达式构造匿名递归函数
    概率论与数理统计-课程小报告
    leetcode226 翻转二叉树
    leetcode199 二叉树的右视图
    leetcode114- 二叉树展开为链表
    leetcode145 二叉树的后序遍历 特别注意迭代
    leet144 二叉树的前序遍历
    leetcode113 路径总和2 特别关注
    leetcode 112 路径总和 特别关注
  • 原文地址:https://www.cnblogs.com/wawawa8/p/10842606.html
Copyright © 2011-2022 走看看