2023.7月初模拟赛总结

2023.7月初模拟赛总结

前言:
近期(约)3天比了3场模拟赛,都源于USACO。但是这3场我的成绩都很低,赛后一看题解被自己的智商哭死,实在看不下去了,决定要写一篇总结

Day 1

T1

P3132 [USACO16JAN] Angry Cows G

正解

DP,设 $f_i$ 为使第 $i$ 个干草堆左边的所有干草堆爆炸的最小力度。
考虑转移方程。

找一个 $j$,满足:

  • $j<i$
  • $a_i-a_j>f_j+1$

会有很多个 $j$,我们需要最后一个,即最靠近 $i$ 的那一个。

易得:

$$ f_i=min(a_i-a_j,f_{j+1}+1) $$

其中 $f_1=0$

类似的,我们可得使右边的爆炸的 $g[]$ 的状态转移方程。

最后我们枚举爆炸点,显然:

$$ ans=min\{max(\frac{a_j-a_i}{2},max(f_i,g_j)+1) \} $$

其中,$i$ 和 $j$ 的互相推进用到了贪心策略。

还有一点,因为最优情况爆炸点只可能在整点或两个整点中间,所以为了避免double精度问题,我们可以都乘以一个 $2$。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define rp(i, o, p) for (ll i = o; i <= p; ++i)
#define pr(i, o, p) for (ll i = o; i >= p; --i)

const ll MAXN = 5e4 + 5, INF = 0x3f3f3f3f;

ll n;
ll f[MAXN], g[MAXN];
ll a[MAXN];

int main() {
    scanf("%lld", &n);
    rp(i, 1, n) scanf("%lld", &a[i]), a[i] *= 2;
    sort(a + 1, a + n + 1);
    memset(f, 0x3f, sizeof(f));
    memset(g, 0x3f, sizeof(g));
    ll t = 1;
    f[1] = 0;
    rp(i, 2, n) {
        while (t + 1 < i && a[i] - a[t + 1] > f[t + 1] + 2) ++t;
        f[i] = min(a[i] - a[t], f[t + 1] + 2);
    }
    t = n;
    g[n] = 0;
    pr(i, n - 1, 1) {
        while (t - 1 > i && a[t - 1] - a[i] > g[t - 1] + 2) --t;
        g[i] = min(a[t] - a[i], g[t - 1] + 2);
    }
    ll ans = INF;
    for (ll i = 1, j = n; i < j;) {
        ans = min(ans, max((a[j] - a[i]) / 2, max(f[i], g[j]) + 2));
        if (f[i + 1] < g[j - 1])
            ++i;
        else
            --j;
    }
    printf("%.1lf", (double)ans / 2);
    return 0;
}

T2

P3133 [USACO16JAN] Radio Contact G

正解

dp,设 $f_{i,j}$ 为在 $(i,j)$ 时最小代价。对于他们的行动串,分别用两个递推数组储存他们的横坐标与纵坐标。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define rp(i, o, p) for (ll i = o; i <= p; ++i)
#define pr(i, o, p) for (ll i = o; i >= p; --i)
#define po(x) ((x) * (x))

const ll MAXN = 1e3 + 5;

ll n, m;
ll fx, fy, cx, cy;
ll f[MAXN][MAXN];
ll ax[MAXN], bx[MAXN], ay[MAXN], by[MAXN];

ll d(ll i, ll j) { return po(fx + ax[i] - (cx + bx[j])) + po(fy + ay[i] - (cy + by[j])); }

int main() {
    scanf("%lld%lld", &n, &m);
    scanf("%lld%lld%lld%lld", &fx, &fy, &cx, &cy);
    rp(i, 1, n) {
        char ch;
        cin >> ch;
        ax[i] = ax[i - 1], ay[i] = ay[i - 1];
        if (ch == 'N')
            ay[i]++;
        if (ch == 'S')
            ay[i]--;
        if (ch == 'W')
            ax[i]--;
        if (ch == 'E')
            ax[i]++;
    }
    rp(i, 1, m) {
        char ch;
        cin >> ch;
        bx[i] = bx[i - 1], by[i] = by[i - 1];
        if (ch == 'N')
            by[i]++;
        if (ch == 'S')
            by[i]--;
        if (ch == 'W')
            bx[i]--;
        if (ch == 'E')
            bx[i]++;
    }
    memset(f, 0x3f, sizeof(f));
    f[0][0] = 0;
    rp(i, 0, n) {
        rp(j, 0, m) {
            if (i != 0)
                f[i][j] = min(f[i][j], f[i - 1][j] + d(i, j));
            if (j != 0)
                f[i][j] = min(f[i][j], f[i][j - 1] + d(i, j));
            if (i != 0 && j != 0)
                f[i][j] = min(f[i][j], f[i - 1][j - 1] + d(i, j));
       }
    }

    printf("%lld\n", f[n][m]);
    return 0;
}

T3

P3134 [USACO16JAN] Lights Out G

正解

按照题意所说,枚举每个点出发的情况。再把路径记录下来,看看这条路径是否唯一。若唯一,则“觉醒”。
我们可以用map储存,路径可以压成 string。
其中对于路径储存问题,我们需要知道这条边的长度与这个角的角度。由于这里的角度不是 270° 就是 90°,所以判断旋转方向即可。

代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define rp(i, o, p) for (ll i = o; i <= p; ++i)
#define pr(i, o, p) for (ll i = o; i >= p; --i)

const ll MAXN = 200 + 5;

ll n;
struct node {
    ll x, y;
} a[MAXN];
map<string, ll> ma;
ll ans;
ll len[MAXN], dis[MAXN];
string ang[MAXN], ls[MAXN];

bool got(ll i, ll j, ll k) {
    bool op;
    if (a[i].x == a[j].x) {
        if (a[j].y > a[i].y) {
            if (a[k].x > a[j].x)
                op = 1;
            else
                op = 0;
        } else {
            if (a[k].x > a[j].x)
                op = 0;
            else
                op = 1;
        }
    } else {
        if (a[j].x > a[i].x) {
            if (a[k].y > a[j].y)
                op = 0;
            else
                op = 1;
        } else {
            if (a[k].y > a[j].y)
                op = 1;
            else
                op = 0;
        }
    }
    return op;
}

inline string work(ll x) {
    string s;
    ll a[10], hd = 0;
    while (x) {
        a[++hd] = x % 10;
        x /= 10;
    }
    pr(i, hd, 1) s += a[i] + 48;
    return s;
}

int main() {
    scanf("%lld", &n);
    rp(i, 1, n) scanf("%lld%lld", &a[i].x, &a[i].y);
    rp(i, 1, n) {
        ll i0 = i - 1, i1 = i + 1;
        if (i0 < 1)
            i0 = n - i0;
        if (i1 > n)
            i1 = i1 - n;
        ang[i] = got(i0, i, i1) ? "A" : "B";
        len[i] = abs(a[i0].x - a[i].x) + abs(a[i0].y - a[i].y);
    }

    rp(i, 1, n) {
        ls[i] = work(len[i]);
        ll t1 = len[1], t2 = len[2];
        if (i == 1)
            continue;
        rp(j, i + 1, n) t1 += len[j];
        pr(j, i - 1, 2) t2 += len[j + 1];
        dis[i] = min(t1, t2);
    }

    rp(i, 2, n) {
        string s;
        s += ang[i];
        ma[s]++;
        rp(j, i + 1, n) {
            s = s + ls[j] + ang[j];
            ma[s]++;
        }
    }

    rp(i, 2, n) {
        ll now = -1;
        string s;
        s += ang[i];
        if (ma[s] == 1)
            continue;
        ll sum = 0;
        rp(j, i + 1, n) {
            s = s + ls[j] + ang[j];
            sum += len[j];
            if (ma[s] == 1) {
                now = j;
                break;
            }
        }
        if (now == -1)
            ans = max(ans, sum + len[1] - dis[i]);
        else
            ans = max(ans, dis[now] + sum - dis[i]);
    }

    printf("%lld\n", ans);

    return 0;
}

总结

同年级rk12,倒数第一……
其实题都不难,可能是脑子抽了……

Day 2

T1

P8901 [USACO22DEC] Circular Barn S

正解

这是巴什博奕。

上来先筛一遍质数,欧拉筛 $O(n)$ 搞定。

经过打表找规律会发现一个房间内只要是对于 $4$ 的倍数,则先手必输。(可以证明,但这里不展开了)

对于先手而言,肯定自己占优时希望能快则快、占劣时能拖则拖。
所以我们记录一下轮数(两人都进行一次操作称为一轮)。

如果是 $4$ 的倍数,两人最优策略都只能不停出 $2$,所以我们这一个房间结束时,经历了 $i/4+1$ 轮。
如果不是,那先手可以取走一个数使得剩下的数右边为 $4$ 的倍数。记录一下 $i \mod 4$ 最大数 $i$。

那么怎么知道答案呢?记录先手获胜时最小轮数 $min_1$ 与这个房间号 $pos_1$,后手同理。
然后比较 $min_1$ 与 $min_2$ 的大小,谁更小,意味着谁更快赢得游戏。
想等的话比较谁的房间号更小。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <cstdio>
using namespace std;

#define ll long long
#define rp(i, o, p) for (ll i = o; i <= p; ++i)
#define pr(i, o, p) for (ll i = o; i >= p; --i)

const ll MAXN = 2e5 + 5, MAXM = 5e6 + 5, INF = 0x7f7f7f7f;

ll T, n;
ll a[MAXN], pri[MAXM], pinum;
bool ispr[MAXM];
ll s[4];
ll ans[MAXM];

inline ll read() {
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
    return x * f;
}

inline void write(ll x) {
    if (x < 0) {
        putchar('-'), write(-x);
        return;
    }
    if (x > 9)
        write(x / 10), putchar(x % 10 + 48);
    else
        putchar(x + 48);
}

void getprime(ll n) {
    ans[1] = 1;
    s[1] = 1;
    for (ll i = 2; i <= n; ++i) {
        if (!ispr[i]) {
            pri[++pinum] = i;
            if (i % 4)
                s[i % 4] = i;
        }
        for (ll j = 1; j <= pinum; ++j) {
            if (i * pri[j] > n)
                break;
            ispr[i * pri[j]] = 1;
            if (i % pri[j] == 0)
                break;
        }
        if (i % 4 == 0)
            ans[i] = i / 4 + 1;
        else
            ans[i] = (i - s[i % 4]) / 4 + 1;
    }
}

int main() {
    getprime(MAXM - 5);
    T = read();
    while (T--) {
        n = read();
        ll min1 = INF, pos1, min2 = INF, pos2;
        rp(i, 1, n) {
            a[i] = read();
            if (a[i] % 4 == 0) {
                if (min2 > ans[a[i]]) {
                    min2 = ans[a[i]];
                    pos2 = i;
                }
            } else {
                if (min1 > ans[a[i]]) {
                    min1 = ans[a[i]];
                    pos1 = i;
                }
            }
        }
        if (min1 < min2)
            puts("Farmer John");
        else if (min1 > min2)
            puts("Farmer Nhoj");
        else {
            if (pos1 < pos2)
                puts("Farmer John");
            else
                puts("Farmer Nhoj");
        }
    }
    return 0;
}

T2

P8903 [USACO22DEC] Bribing Friends G

正解

dp,但是需要优化。
$O(n^3)$ 的朴素dp这里不说了,直接说正解。

设 $f_{i,j}$ 为遍历了前 $i$ 个人,花了 $j$ 个雪糕可以得到的最大利润。
设 $g_{i,j}$ 为花了 $j$ 元的最大利润。

然后我们枚举在哪一个人身上既花雪糕又花钱。
这显然可以证明只会有一个人既花雪糕又花钱,那他前面的就都用雪糕、后面的就都用钱来支付。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define rp(i, o, p) for (ll i = o; i <= p; ++i)
#define pr(i, o, p) for (ll i = o; i >= p; --i)

const ll MAXN = 2e3 + 5;

ll n, A, B;
ll f[MAXN][MAXN];
ll g[MAXN][MAXN];
struct node {
    ll p, c, x, xc;
    bool operator<(const node &t) const { return x < t.x; }
} a[MAXN];

int main() {
    scanf("%lld%lld%lld", &n, &A, &B);
    rp(i, 1, n) {
        ll x, y, z;
        scanf("%lld%lld%lld", &x, &y, &z);
        a[i] = { x, y, z, y * z };
    }

    sort(a + 1, a + n + 1);

    rp(i, 1, n) {
        rp(j, 0, B) f[i][j] = f[i - 1][j];
        pr(j, B, a[i].xc) f[i][j] = max(f[i][j], f[i - 1][j - a[i].xc] + a[i].p);
    }

    pr(i, n, 1) {
        rp(j, 0, A) g[i][j] = g[i + 1][j];
        pr(j, A, a[i].c) g[i][j] = max(g[i][j], g[i + 1][j - a[i].c] + a[i].p);
    }

    ll ans = 0;
    rp(i, 1, n) {
        ans = max(ans, max(f[i - 1][B] + g[i][A], f[i][B] + g[i + 1][A]));
        for (ll j = 0; j <= min(A, a[i].c); ++j) {
            if (B < (a[i].c - j) * a[i].x)
                continue;
            ans = max(ans, f[i - 1][B - (a[i].c - j) * a[i].x] + g[i + 1][A - j] + a[i].p);
        }
    }

    printf("%lld\n", ans);

    return 0;
}

T3

P8904 [USACO22DEC] Mountains G

正解

暴力膜你模拟。
我们每个山峰都建一个set,记录他右边能看到的山有哪些。

在修改一座山 $x$ 的数据后,判断山 $x$ 会不会挡住山 $i$ 本来能看见的一些山。若挡住,则将山 $x$ 右边的山从 $s_i$ 中删掉。
对于山 $x$ 本身,重构就好了。

能互相看到的山的对数在这个过程中也可以统计出来。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <cstdio>
#include <set>
using namespace std;

#define ll long long
#define rp(i, o, p) for (ll i = o; i <= p; ++i)
#define pr(i, o, p) for (ll i = o; i >= p; --i)
#define ins insert
#define era erase
#define upp upper_bound
#define low lower_bound

const ll MAXN = 2e3 + 5;

ll n, ans;
ll a[MAXN];
set<ll> s[MAXN];

double gotk(ll i, ll j) { return 1.0 * (a[j] - a[i]) / (j - i); }

int main() {
    scanf("%lld", &n);
    rp(i, 1, n) scanf("%lld", &a[i]);
    rp(i, 1, n) {
        s[i].ins(0), s[i].ins(n + 1);
        double k = -1e9;
        rp(j, i + 1, n) {
            if (gotk(i, j) >= k) {
                k = gotk(i, j);
                s[i].ins(j);
                ++ans;
            }
        }
    }

    ll Q;
    scanf("%lld", &Q);
    while (Q--) {
        ll ix, h;
        scanf("%lld%lld", &ix, &h);
        a[ix] += h;
        rp(i, 1, ix - 1) {
            auto it = s[i].low(ix);
            it--;
            ll y = *it;
            if (y && gotk(i, y) > gotk(i, ix))
                continue;
            if (s[i].find(ix) == s[i].end())
                s[i].ins(ix), ++ans;
            for (y = *s[i].upp(ix); y <= n; y = *(s[i].upp(y))) {
                if (gotk(i, y) >= gotk(i, ix))
                    break;
                s[i].era(y), --ans;
            }
        }
        ans -= s[ix].size() - 2;
        s[ix].ins(0), s[ix].ins(n + 1);
        double k = -1e9;
        rp(i, ix + 1, n) {
            if (gotk(ix, i) >= k) {
                k = gotk(ix, i);
                s[ix].ins(i);
                ++ans;
            }
        }
        printf("%lld\n", ans);
    }

    return 0;
}

总结

同级rk5,但是大家都没打好,太难了,没有人A。

可能是我这次比较走运。

Day 3

补题去了。
顺便一提,一道绿题做了一天……

其实还是很简单的,但是我的脑细胞却死了不少。。

罪魁祸首:

Day 4

T1

P3090 [USACO13NOV] Empty Stalls G

正解

签到题,但是我没做出来。

赛后看了题解,只要扫一遍就好了,注意要再扫一轮,以免一些特殊情况。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <set>
#include <cstdio>
using namespace std;

#define int long long
#define rp(i, o, p) for (int i = o; i <= p; ++i)
#define pr(i, o, p) for (int i = o; i >= p; --i)

const int MAXN = 3e6 + 5, MAXK = 1e4 + 5;

int n, k;
int num[MAXN];

signed main() {
    scanf("%lld%lld", &n, &k);
    rp(i, 1, k) {
        int x, y, a, b;
        scanf("%lld%lld%lld%lld", &x, &y, &a, &b);
        rp(j, 1, y) {
            int t = a * j % n + b % n;
            t %= n;
            num[t] += x;
        }
    }
    rp(i, 0, n - 1) {
        if (num[i]) {
            num[(i + 1) % n] += num[i] - 1;
            num[i] = 1;
        }
    }
    if (num[0])
        for (int i = 0; i < n; ++i) {
            if (num[i]) {
                num[(i + 1) % n] += num[i] - 1;
                num[i] = 1;
            }
        }
    rp(i, 0, n - 1) if (!num[i]) {
        printf("%lld\n", i);
        break;
    }

    return 0;
}

T2

P3088 [USACO13NOV] Crowded Cows S

正解

又是签到题,可是我又傻了。

单调队列维护最大值,然后判断即可。
注意正反都做一遍,可以做到 $O(n)$。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

#define int long long
#define rp(i, o, p) for (int i = o; i <= p; ++i)
#define pr(i, o, p) for (int i = o; i >= p; --i)

const int MAXN = 1e5 + 5;

int n, d;
struct node {
    int x, h;
    bool operator<(const node &t) const { return x < t.x; }
} a[MAXN], q[MAXN];
bool l[MAXN], r[MAXN];

signed main() {
    scanf("%lld%lld", &n, &d);
    rp(i, 1, n) scanf("%lld%lld", &a[i].x, &a[i].h);
    sort(a + 1, a + n + 1);

    int lf = 1, rg = 0;
    rp(i, 1, n) {
        while (lf <= rg && q[rg].h < a[i].h) --rg;
        q[++rg] = a[i];
        while (lf <= rg && q[lf].x < a[i].x - d) ++lf;
        if (q[lf].h >= a[i].h * 2)
            l[i] = 1;
    }
    memset(q, 0, sizeof(q));
    lf = 1, rg = 0;
    pr(i, n, 1) {
        while (lf <= rg && q[rg].h < a[i].h) --rg;
        q[++rg] = a[i];
        while (lf <= rg && q[lf].x > a[i].x + d) ++lf;
        if (q[lf].h >= a[i].h * 2)
            r[i] = 1;
    }

    int ans = 0;
    rp(i, 1, n) if (l[i] && r[i])++ ans;
    printf("%lld\n", ans);

    return 0;
}

T3

P3089 [USACO13NOV] Pogo-Cow S

正解

dp,容易想到设 $f_{i,j}$ 为第 $i$ 点,从第 $j$ 点跳过来的最大分值。

可得

$$ f_{i,j}=f_{j,k}+p_i $$

但是会爆。 若 $i\to i-1$

$$ f_{i-1,j}=f_{j,k}+p_{i-1} $$

结合一下,得

$$ f_{i,j}=f_{i-1,j}-p_{i-1}+p_i $$

好像没 $k$ 什么事了。

我们思考一下,如果固定 $j$ 点,$i$ 点与 $k$ 点的变换类似于共同进行,所以我们可以在同一个循环中搞定。

时间复杂度 $O(n^2)$。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1e3 + 5;

int n;
struct node {
    int x, p;
    bool operator<(const node &t) const { return x < t.x; }
} a[MAXN];
int ans;
int f[MAXN][MAXN];

signed main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].x, &a[i].p);
    sort(a + 1, a + n + 1);

    for (int j = 1; j <= n; ++j) {
        f[j][j] = a[j].p;
        int k = j + 1;
        for (int i = j + 1; i <= n; ++i) {
            f[i][j] = f[i - 1][j] - a[i - 1].p;
            while (k > 1 && a[j].x - a[k - 1].x <= a[i].x - a[j].x) f[i][j] = max(f[i][j], f[j][--k]);
            f[i][j] += a[i].p;
            ans = max(ans, f[i][j]);
        }
        ans = max(ans, f[j][j]);
    }

    for (int j = n; j >= 1; --j) {
        f[j][j] = a[j].p;
        int k = j - 1;
        for (int i = j - 1; i >= 1; --i) {
            f[i][j] = f[i + 1][j] - a[i + 1].p;
            while (k < n && a[k + 1].x - a[j].x <= a[j].x - a[i].x) f[i][j] = max(f[i][j], f[j][++k]);
            f[i][j] += a[i].p;
            ans = max(f[i][j], ans);
        }
        ans = max(ans, f[j][j]);
    }

    printf("%d\n", ans);

    return 0;
}

总结

同级倒数第一,有两个人AK……

总总结

“开动脑筋。”这是教练常说的话。

确实,这个暑假如果不改变不勤思考的习惯,只会被淘汰。

Licensed under CC BY-NC-SA 4.0