2021.4.30 校内模拟赛游记

不想说什么了。

A

说难不难说简单不简单的一道题。

“说难不?难。说简单!不简单。”的一道题。

“说难不难。说简单不?简单。”的一道题。

好了好了不整活了

给定 nn 个括号序列,能否将其拼成一个匹配的括号序列。

这道题其实是考察思维的严谨性。

首先的想法是是否个数相等就行。这显然是不行的。

观察得到肯定要是去除匹配之后全左和全右的在两边。于是我就认为两边有中间匹配就行。

然后 WA 了。

发现了反例,觉得中间要判断一下才行。

然后又 WA 了。

接着又觉得要把右括号少的放前面。

又双叒叕 WA 了。

其实以上的反例都特别好找,而且都没有严谨的理论基础,只是找了几个数据就凭着感觉上的,和直接猜结论没有本质的区别。

所以有了例子还是得从理论出发找到做法。

  1. 最左边右括号不能没有匹配
  2. 保证了前面不会出事的情况下肯定是左括号越多越好,以应对未来的右括号。

根据这个排序即可。这个想法似乎也有所特别,和大部分人的不一样。

代码。

#include <bits/stdc++.h>
std::string s, tmp, stl, str, stn;
char st[1000005];
int numl, numr, n, lenl, lenr;
struct twt {
    std::string st;
    int k;
    bool operator<(twt b) const {
        return (k <= stl.size()) > (b.k <= stl.size()) ||
               ((k <= stl.size()) == (b.k <= stl.size()) && st.size() - k > b.st.size() - b.k);
    }
};
std::vector<twt> a;
bool checkl(std::string s) {
    if (s.size() == 0)
        return false;
    for (int i = 0; i < (signed)s.size(); i++)
        if (s[i] == ')')
            return false;
    return true;
}
bool checkr(std::string s) {
    if (s.size() == 0)
        return false;
    for (int i = 0; i < (signed)s.size(); i++)
        if (s[i] == '(')
            return false;
    return true;
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin >> n;
    for (int i = 1; i <= n; i++) {
        std::cin >> tmp;
        s = "";
        int top = 0;
        for (int j = 0; j < (signed)tmp.size(); j++)
            if (tmp[j] == ')') {
                if (st[top] == '(')
                    top--;
                else
                    st[++top] = ')';
            } else
                st[++top] = '(';
        for (int j = 1; j <= top; j++) s = s + st[j];
        if (checkl(s))
            stl += s;
        else if (checkr(s))
            str += s;
        else {
            int k = 0;
            for (int j = 0; j < (signed)s.size(); j++) k += s[j] == ')';
            a.push_back(twt{ s, k });
        }
    }
    std::sort(a.begin(), a.end());
    std::string an = stl;
    for (int i = 0; i < (signed)a.size(); i++) an += a[i].st;
    an += str;
    // std::cout << an << std::endl;
    int now = 0;
    for (int i = 0; i < (signed)an.size(); i++) {
        if (an[i] == '(')
            now++;
        else
            now--;
        if (now < 0)
            return puts("No"), 0;
    }
    if (now != 0)
        puts("No");
    else
        puts("Yes");
}

花了我一小时二十分钟qwq。

B

水题

C

水题

E

有点细节啊,就是要处理一个部分循环的问题,但还是花了好久。

D

不难的组合数学。

nn 个格子填 mm 种颜色,使相邻的格子不能有 kk 个以上颜色相同的方案数。

先插板,然后再乘法原理 m×(m1)×(m1)m\times(m-1)\times(m-1) \dots

答案就是 i=0kCn1ni1m(m1)ni1\sum_{i=0}^k C_{n-1}^{n-i-1}m (m-1)^{n-i-1}

最后

名次全无往日威风了。

感觉状态不增反降,越来越差了。

越是没法静心做题,就越是没法面对自己;越是没法面对自己,就越是没法静心做题。