【套题】Codeforces#306(div2)[A-C]

A. Two Substrings

  • 题意:问一个字符串中是否同时存在AB和BA,其中AB和BA不能共用同一个B或A。
  • 题解:扫一遍即可。可以考虑如下策略:先找AB,然后从B后的位置继续找BA;再另按BA-AB的顺序找一遍即可。复杂度 O(n) 。窝的代码则直接暴力出所有的AB和BA位置,只要出现不重叠的两个就 OK ~数据不大,随便搞。
  • 参考代码:
#include <bits/stdc++.h>
using namespace std;

int main() {
    string str;
    while (cin >> str) {
        vector<int> ab;
        vector<int> ba;
        for (int i = 0; i < str.length() - 1; ++i) {
            if (str[i] == 'A' && str[i + 1] == 'B') {
                ab.push_back(i);
            } else if (str[i] == 'B' && str[i + 1] == 'A') {
                ba.push_back(i);
            }
        }
        bool flag = false;
        for (int i = 0; i < ab.size(); ++i) {
            for (int j = 0; j < ba.size(); ++j) {
                if (abs(ab[i] - ba[j]) > 1) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                break;
            }
        }
        cout << (flag ? "YES" : "NO") << endl;
    }
    return 0;
}

B. Preparing Olympiad

  • 题意: n 个问题,每个问题有一个难度值,要选出来一些。问满足以下条件的方案数:
    • 至少选2个
    • 难度值的和在区间[l,r]
    • 最难和最简单的问题间的难度值差要 x
    • 题解:数据很小 (n15) ,因此我们可以 O(2n) 地枚举子集即可。为了方便讨论,可以先排序一下,这样的话前缀和以及难度差都可以平均 O(1) 地得到。
    • 参考代码:
    • #include <bits/stdc++.h>
      using namespace std;
      
      const int MAX = 16;
      int sum[MAX];
      int c[MAX];
      int n, l, r, x;
      
      bool check(int state) {
          int sum = 0, mind = 0xfffffff, maxd = -1;
          for (int i = 0; i < n; ++i) {
              if (state & 1) {
                  sum += c[i];
                  if (c[i] > maxd) {
                      maxd = c[i];
                  }
                  if (c[i] < mind) {
                      mind = c[i];
                  }
              }
              state >>= 1;
          }
          if (sum < l || sum > r || (maxd - mind) < x) {
              return false;
          }
          return true;
      }
      
      int main() {
          while (~scanf(" %d %d %d %d", &n, &l, &r, &x)) {
              for (int i = 0; i < n; ++i) {
                  scanf(" %d", c + i);
              }
              sort(c, c + n);
              memset(sum, 0, sizeof(sum));
              sum[0] = c[0];
              for (int i = 1; i < n; ++i) {
                  sum[i] = sum[i - 1] + c[i];
              }
      
              int ans = 0;
              for (int i = 0; i < (1 << n); ++i) {
                  if (check(i)) {
                      ans++;
                  }
              }
              printf("%d\n", ans);
          }
          return 0;
      }

      C. Divisibility by Eight

      • 题意:给个不超过100位的数,删掉一些位上的数字,能否得到一个能被8整除的值。
      • 题解:考虑阉割后的结果 x 满足x%8=0,由于 1000%8=0 ,如果 x 的位数大于3位:设
        y=x%1000
        z=x1000
        那么 x=y+z ,由于 z%1000=0 ,必然有 z%8=0 ,于是只需要判断是否 y%8=0 即可。也就是说,我们只需要判断 x <script type="math/tex" id="MathJax-Element-19">x</script>的后3位即可,也正因此,我们最多只需要找3位即可。数据不大可以直接枚举出来。对于少于2位的情况,当然也可以直接枚举。窝则枚举了1000以内的8的倍数,再依次暴力判断。
      • 参考代码:
      #include <bits/stdc++.h>
      using namespace std;
      
      pair<bool, string> judge1(string x) {
          for (int i = x.length() - 1; i >= 0; --i) {
              if (x[i] == '0') {
                  return make_pair(true, "0");
              }
          }
          return make_pair(false, "joke");
      }
      
      bool judge2(int x) {
          if (x == 0) {
              return false;
          }
          while (x) {
              if (x % 10 == 0) {
                  return false;
              }
              x /= 10;
          }
          return true;
      }
      
      string toString(int x) {
          string res = "";
          if (x == 0) {
              res = "0";
          }
          while (x) {
              res = (char)(x % 10 + '0') + res;
              x /= 10;
          }
          return res;
      }
      
      void init(vector<string>& x) {
          for (int i = 1; i < 1000; ++i) {
              if (i % 8 == 0 && judge2(i)) {
                  //printf("push %d\n", i);
                  x.push_back(toString(i));
              }
          }
      }
      
      pair<bool, string> judge3(string x, string sub) {
          //cout << "Judge3(" << x << ", " << sub << ")" << endl;
          int i = 0, j = 0;
          while (i < x.size() && j < sub.size()) {
              if (x[i] == sub[j]) {
                  ++i;
                  ++j;
              } else {
                  ++i;
              }
          }
          if (j == sub.size()) {
              return make_pair(true, sub);
          } else {
              return make_pair(false, "fuck");
          }
      }
      
      int main() {
          //cout << toString(344) << endl;
          vector<string> box;
          init(box);
          string num;
          while (cin >> num) {
              pair<bool, string> ans = judge1(num);
              if (ans.first) {
                  cout << "YES\n0" << endl;
              } else {
                  bool flag = false;
                  for (int i = 0; i < box.size(); ++i) {
                      ans = judge3(num, box[i]);
                      if (ans.first) {
                          cout << "YES\n" << ans.second << endl;
                          flag = true;
                          break;
                      }
                  }
                  if (!flag) {
                      cout << "NO" << endl;
                  }
              }
          }
      
          return 0;
      }

      D和E留着下次补…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值