湖南工程学院 学科实践与创新协会电气部 幕后揭示

~献给挚爱的你的不思议之国幕后揭示

题面地址:https://www.cnblogs.com/Reisentyan/p/19261758

现在时间:\([2025/11/20\) \(23:47]\)

将揭示——

幕后真相

本场比赛难度预计:

  • Easy - A, B, C
  • Normal - D, E, H
  • Hard - G, I, J
  • Lunatic - F

截至目前,各题通过情况统计如下:

题目 提交次数 通过次数 通过率
A:铃仙的不思议之国 提交86 通过29 33.72%
B:魔法使基本:算法导论 提交86 通过19 22.09%
C:铃波那契数列 提交104 通过25 24.04%
D:纸牌士兵 提交76 通过5 6.58%
E:命中注定 提交32 通过16 50.00%
F:库因兰德(Q Island) 提交40 通过8 20.00%
G:魔法使提高:标准模板 提交46 通过24 52.17%
H:凝滞的白之庭院 提交34 通过13 38.24%
I:亿万年的星光 提交13 通过12 92.31%
J:献给挚爱的你的不思议之国 提交35 通过19 54.29%

实际比赛难度分布:

  • Easy - A, C, G
  • Normal - B, E, J
  • Hard - H, I
  • Lunatic - D, F

这个结果可以说是相当出人意料。

大家的代码我都粗略看了一遍,发现:

  • 为何 D 题通过率如此之低?主要原因在于题面没有给出机器人名字长度的上限,很多同学默认最长为 100。只要把名字长度数组开到 10000,或者使用动态字符串,就能避免这一类错误。
  • 赛前认为 F 题是全场最难,本来没打算出到这个强度。但由于同时存在传送与转向两种法阵,叠在一起后复杂度明显上去了。试题包中的前四组数据还是空数据,在此向大家致歉,之后在洛谷上已经删除了有问题的数据。
  • D、F、H 题中,很多代码都写错了方向或边界,属于比较典型的“实现细节翻车”。这些题本身并不要求高深算法,更多是在考察调试能力和对细节的敏感度。
  • I 题通过率异常之高,是因为这是一个非常经典的背包模型,建议还没写的同学认真补一补。
  • A 题本身难度不大,但因为刚开场不少同学在尝试各种写法,常见错误包括:没有使用 long long、输入输出格式写错,甚至把 01 搞反。

希望大家在赛后多对照题解,把这些细节问题都真正吃透。

A:铃仙的不思议之国

最简单的钥匙,也能打开通往幻想的大门。

题解:

#include <stdio.h>

int main()
{
    long long num1 = 0;
    long long num2 = 0;
    long long num3 = 0;
    scanf("%lld %lld %lld", &num1, &num2, &num3);

    if (num2 % 2 == 0)
    {
        printf("%lld\n", num1 - num3);
    }
    else
    {
        printf("%lld\n", num1 + num3);
    }

    return 0;
}

仔细看题面可以发现,num1num3 可能会非常大,int 型是存不下的,必须使用 long long(即 long long int)。

还有就是,别把1看成0,你不是人工智能

这道题主要是让大家熟悉洛谷的评测环境,以及基础的输入输出和数据类型选择。


B:魔法使基本:算法导论

区间的总和,是程序理解世界的第一种方式,也是人理解程序的第一步。

题解:

#include <stdio.h>

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    long long num[n + 1];
    num[0] = 0;
    
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &num[i]);
        num[i] += num[i - 1]; // 计算前缀和
    }
    
    for (int i = 0; i < m; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        
        if (x > y) {
            int temp = x;
            x = y;
            y = temp;
        }
        
        printf("%lld\n", num[y] - num[x - 1]);
    }
    
    return 0;
}

前缀和作为最基础、也最常用的算法之一,在从入门练习到各种高级题目中都有身影,本题就是一个很典型的应用场景。

题面没有显式给出数据范围,但要意识到区间和可能会非常大,用 int 很容易溢出,建议一律使用 long long 存储前缀和。

还有不少同学因为没有使用前缀和,而是每次询问都从头循环求和,导致超时。

这类问题只要写对前缀和,时间复杂度就能从 \(O(nm)\) 直接优化到 \(O(n + m)\)


C:铃波那契数列

递推是算法的记忆,而公式是人类试图驯服它的语言。

题解:

#include <stdio.h>

#define MOD 998244353

long long lbnq[1001000];

int main() {
    lbnq[0] = lbnq[1] = lbnq[2] = 1;
    
    for (int i = 3; i <= 1000000; i++) {
        lbnq[i] = lbnq[i - 1] + lbnq[i - 2] - lbnq[i - 3] + 1 + MOD;
        lbnq[i] %= MOD;
    }
    
    int x;
    scanf("%d", &x);
    printf("%lld\n", lbnq[x]);
    
    return 0;
}

冷知识:这个数列的名字其实并不叫铃波那契(笑)

这是一个非常经典的数列,叫什么名字我忘记了

上面的递推写法是一种做法,还有同学给出了更巧妙的闭式表达式

例如把答案按奇偶性拆成两种情况,写成关于 $(\left\lfloor \dfrac{n}{2} \right\rfloor) $的多项式形式,形式大致如下(节选自一份提交):

long long m = n / 2;
long long result;

if (n % 2 == 0) {
        // 如果 n 是偶数, f(n) = 1 + m * (m - 1)
        long long term1 = m % MOD;
        long long term2 = (m - 1) % MOD;
        // 处理 term2 可能为负数的情况
        if (term2 < 0) term2 += MOD;
        result = (1 + (term1 * term2) % MOD) % MOD;
    } else {
        // 如果 n 是奇数, f(n) = 1 + m * m
        long long term = m % MOD;
        result = (1 + (term * term) % MOD) % MOD;
    }

有兴趣的同学可以自行搜索这个数列的来历和推导过程,会发现不少有趣的数学小知识。非常感谢这位同学!

这个题我故意将数据填到\(10^9\),其实数据只有\(10^6\),想借此卡住ai

其实ai写矩阵快速幂很稳,一次就通过,矩阵快速幂是一个很实用的算法,只是编码难度高了一点

只要一路算到n,取模不出错就可以了,记得开longlong


D:纸牌士兵

排序不是比较大小,而是在混乱中找回秩序。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Robot {
    int va[3];       // 速度、耐久、力量
    char name[10005];  // 名字
};

int cmp(const void *a, const void *b) {
    const struct Robot *ra = (const struct Robot *)a;
    const struct Robot *rb = (const struct Robot *)b;

    extern int y; // 排序依据的性能指标(全局声明)

    if (ra->va[y - 1] != rb->va[y - 1]) {
        return rb->va[y - 1] - ra->va[y - 1];  // 该性能值降序
    }
    return strcmp(ra->name, rb->name);  // 名称字典序升序
}

int y; // 作为排序依据的全局变量

int main() {
    int n, x;
    scanf("%d %d", &n, &x);

    struct Robot *arr = (struct Robot *)malloc(sizeof(struct Robot) * n);
    if (!arr) return 0;

    for (int i = 0; i < n; i++) {
        scanf("%d %d %d %s",
              &arr[i].va[0],
              &arr[i].va[1],
              &arr[i].va[2],
              arr[i].name);
    }

    scanf("%d", &y);

    qsort(arr, n, sizeof(struct Robot), cmp);

    int lim = (x < n ? x : n);
    for (int i = 0; i < lim; i++) {
        printf("%s %d\n", arr[i].name, arr[i].va[y - 1]);
    }

    free(arr);
    return 0;
}

这道结构体排序题,是我认为本场中最值得大家认真掌握的一题。

在实际工程场景中,带有多种属性的记录(例如“名称 + 多个数值指标”)非常常见,用结构体配合排序是最自然的写法。

本题的排序规则也很典型:先按某一维度降序,再按名字的字典序升序。

出错比较多的一个原因,是题面没有给出机器人名字长度的上限,很多同学直接把名字长度写死为 100,导致字符串被截断或者内存越界。只要把数组开大一些(比如 10000),或者改用动态分配、malloc 等方式,就能规避这一类问题。

之后在洛谷题面加上提示:机器人的名字长度可能有一万位,于是ac率直线上升了

我想说的是,大家需要学会debug


E:命中注定

括号匹配是人和编译器之间最基本的信任。

#include <stdio.h>

#define MAXN 1000005  /* 括号串长度 < 1e6,预留一点空间 */

char s[MAXN];
char st[MAXN];  /* 手写一个栈 */
int top = -1;   /* 栈顶指针,-1 表示空栈 */

int main(void) {
    if (scanf("%s", s) != 1) {
        return 0;
    }

    for (int i = 0; s[i] != '\0'; i++) {
        if (s[i] == '(') {
            /* 左括号直接入栈 */
            st[++top] = '(';
        } else if (s[i] == ')') {
            /* 遇到右括号 */
            if (top < 0) {
                /* 栈空,说明目前为止右括号太多,直接把这个右括号压栈 */
                st[++top] = ')';
            } else if (st[top] == '(') {
                /* 栈顶是左括号,可以成功匹配,弹栈 */
                top--;
            } else {
                /* 栈顶是右括号,无法匹配,只能把这个右括号也压栈 */
                st[++top] = ')';
            }
        }
    }

    if (top == -1) {
        /* 栈空,说明所有括号完全匹配 */
        printf("YES\n");
    } else {
        /* 栈非空,栈里剩下的就是所有“不成对”的括号个数 */
        printf("NO\n");
        printf("%d\n", top + 1);
    }

    return 0;
}

这个题可能大家会觉得莫名其妙,实际上背后对应的是一个非常基础的自动机/语法分析模型。

c语言是一个面向过程的语言,对于不同的状态你需要使用不同的操作

用栈维护“尚未被配对的括号集合”:

  • 遇到 '(' 就入栈;
  • 遇到 ')' 时,若栈顶为 '(' 则弹栈配对,否则将 ')' 压入栈中。

遍历结束后,若栈为空,则原串是一个合法括号序列;否则栈中剩余的元素个数,就是至少需要补上的括号数量。

可以把最终的形态想象成类似于 )))))((((( 这样的结构:前面一串多余的右括号,后面一串多余的左括号,每一个都需要再补一个相反方向的括号才能配平。

难度不高,但这个模型在之后的表达式解析、编译原理等课程中会一再出现,建议大家在心里把“括号匹配 = 栈”的映射牢牢记住。

很经典的题,大家的通过率都很高


F:库因兰德(Q Island)

如果一门语言不能拿来写模拟题,那它也就只剩下 Hello World 了。

#include <stdio.h>

#define MAXN 305
#define MAXM (MAXN * MAXN + 5)

/* 棋盘上的法阵编号,0 表示没有法阵 */
int ma[MAXN][MAXN];

/* 每个法阵编号对应的 (x, y),传送法阵存目标坐标,转向法阵存 (-1, -1) */
int opx[MAXM], opy[MAXM];

int main(void) {
    int n = 0, m = 0, k = 0;
    if (scanf("%d", &n) != 1) return 0;
    scanf("%d", &m);

    /* 传送法阵:编号 1 ~ m */
    for (int i = 1; i <= m; i++) {
        int a, b, c, d;
        scanf("%d %d %d %d", &a, &b, &c, &d);
        ma[a][b] = i;
        opx[i] = c;
        opy[i] = d;
    }

    /* 转向法阵:编号 m+1 ~ m+k,目标坐标存 (-1, -1) */
    scanf("%d", &k);
    for (int i = 1; i <= k; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        int idx = m + i;
        ma[a][b] = idx;
        opx[idx] = -1;
        opy[idx] = -1;
    }

    int nowx = 1, nowy = 1;  /* 当前所在格子 */
    int nowd = 0;            /* 当前方向:0,1,2,3 */

    /* 方向定义
       dx[0] =  1, dy[0] =  0  (“向右”,即 x+1)
       dx[1] =  0, dy[1] = -1  
       dx[2] = -1, dy[2] =  0
       dx[3] =  0, dy[3] =  1
    */
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, -1, 0, 1};

    int cnt = 0;  /* 步数计数,用来防止死循环 */

    /* 只要没到 (n, n) 就一直走 */
    while (nowx != n || nowy != n) {
        /* 出界:直接把位置重置到 (1,1) 并跳出循环 */
        if (nowx > n || nowx < 1 || nowy > n || nowy < 1) {
            nowx = 1;
            nowy = 1;
            break;
        }

        /* 防止死循环:超过 n*n*5 步就认为不可能到达,跳出 */
        if (cnt > n * n * 5) {
            break;
        }

        int p = ma[nowx][nowy];  /* 当前格子上的法阵编号(若为 0 则没有法阵) */
        if (p) {
            int c = opx[p];
            int d = opy[p];

            if (c == -1 && d == -1) {
                /* 转向法阵:顺时针旋转 90° */
                nowd += 1;
                if (nowd >= 4) nowd -= 4;
            } else {
                /* 传送法阵:直接传送到 (c, d),并计一步 */
                nowx = c;
                nowy = d;
                cnt++;
                /* 传送后立刻重新处理新位置上的法阵,因此 continue */
                continue;
            }
        }

        /* 按当前方向走一步 */
        nowx += dx[nowd];
        nowy += dy[nowd];
        cnt++;
    }

    /* 结束后,判断是否停在 (n, n) */
    if (nowx == n && nowy == n) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }

    return 0;
}

最难的题,其实我一开始没有想过出这么难的,结果非常出乎我的意料

在没有图片的方向的提示下,所有ai都默认向右是y-1,这也是卡住大部分同学的原因,大家只要检查一下方向,还是能过不少人

还有就是,大多数ai都会使用bfs的方式,我也不清楚是什么原理,都没有想过直接模拟一步一步走

因此,我一度以为,是数据出错了,后来检查发现,好家伙真的错了,前4个样例输入为空,我也没搞清楚怎么回事

于是就删掉出错的数据了,再次跟大家说声抱歉,后来验证,其他数据都没错

这道题对于大部分同学来说,都是一道不错的练手题

非常适合练习“模拟 + 状态追踪 + 调试能力”的题目,如果赛时没有写出来,赛后一定要找时间把它补完。


G:魔法使提高:标准模板

STL 写起来很爽,但用纯 C 写一遍,你才会真懂它在干什么。

#include <stdio.h>

#define MAXN 100000    /* n < 100000 */
#define MAXLEN 105     /* 字符串长度 < 100 */

char name[MAXN][MAXLEN]; /* 存所有字符串 */
int head[10005];         /* 每个桶(余数)的链表头下标,-1 表示该桶为空 */
int nxt[MAXN];           /* 单链表 next 指针 */
int main(void) {
    long long x;  /* 模数 */
    int n;        /* 元素个数 */

    if (scanf("%lld %d", &x, &n) != 2) {
        return 0;
    }

    /* 初始化所有桶为空 */
    for (int i = 0; i < 10005; i++) {
        head[i] = -1;
    }

    for (int i = 0; i < n; i++) {
        long long V;
        /* 读入数值和字符串 */
        scanf("%lld %s", &V, name[i]);

        int r = (int)(V % x);  /* 计算 V % x 作为桶编号 */

        /* 模拟 stack<string>:新来的元素插到链表头,相当于栈顶 */
        nxt[i] = head[r];
        head[r] = i;
    }

    /* 按桶编号从小到大输出(对应 C++ 里 map 的 key 升序) */
    for (int r = 0; r < x; r++) {
        if (head[r] == -1) continue;  /* 如果该桶为空,就不输出这一行 */

        printf("%d ", r);

        /* 按链表顺序输出,这里因为是“头插法”,顺序就是栈的 LIFO 顺序 */
        int idx = head[r];
        while (idx != -1) {
            printf("%s ", name[idx]);
            idx = nxt[idx];
        }
        printf("\n");
    }

    return 0;
}

这道题主要是想考数据结构,其实题目的要求十分清晰明了了,直接交给ai就可以一次ac

如果出现bug,只要你看得懂代码就可以自行修改

标准模板是什么?在 C++ 世界里,有一套非常强大、非常常用、几乎所有竞赛选手都离不开的工具,这就是:

STL(Standard Template Library,标准模板库)

如果把编程比喻成做菜,那么——

  • C 语言是从买菜 → 洗菜 → 切菜 → 全部自己动手
  • C++ STL 是别人已经 洗好、切好、腌好 的食材,你只需要直接 炒锅里一倒 就能出菜

其实要求大家用c语言写这道题比较困难。所以我把这题的难度标高了很多

虽然但是,这题还是很重要的


H:凝滞的白之庭院

二分查找让计算机更冷静,也逼着人类更精确。

#include <stdio.h>

#define MAXN 10005

long long h[MAXN];

int main(void) {
    int n;
    long long x;

    scanf("%d %lld", &n, &x);

    for (int i = 1; i <= n; i++) {
        scanf("%lld", &h[i]);
    }

    /* 与你原代码一致的二分边界 */
    long long l = 1;
    long long r = 0x3f3f3f3f3f3f3f3f;   /* 一个非常大的数(充当右边界) */

    while (r >= l) {
        long long mid = (l + r) >> 1;

        long long cnt = 0;
        for (int j = 1; j <= n; j++) {
            cnt += h[j] / mid;   /* 每棵树最多能切多少段长度为 mid 的木材 */
        }

        if (cnt < x) {
            /* mid 太大,导致切出来的段数不足,需要缩小段长 */
            r = mid - 1;
        } else {
            /* mid 还可以继续往大试 */
            l = mid + 1;
        }
    }

    /* 根据你原 C++ 代码的写法,答案输出 l-1 */
    printf("%lld\n", l - 1);

    return 0;
}

正如题目下方的小字所说,没有二分就没有算法,这道题作为算法的经典代表,很有做的价值。

可以把这一类题想象成在 \(0\)\(100\) 之间猜一个数字:每次询问的反馈只有“偏大”或“偏小”

你自然会先猜 \(50\),然后根据反馈把区间缩小一半,再尝试区间中点。

真正的二分查找也是同样的思想,只不过这里我们是在数轴上查找“能否切出至少\(x\)段”的分界点。

大部分同学的错误集中在两个方面:一是没有使用 long long 处理大数据

二是二分边界条件写错,导致死循环或答案偏一位。建议在草稿上先写出区间变化过程,再对照代码逐步模拟。


I:亿万年的星光

解决 NP 难题前,先把背包 DP 写顺手。

#include <stdio.h>

#define MAXK 15005  /* k < 15000 */
int dp[MAXK];       /* 一维 DP 数组,dp[j] 表示容量为 j 时的最大价值 */

int main(void) {
    int n, k;
    if (scanf("%d %d", &n, &k) != 2) {
        return 0;
    }

    for (int i = 0; i < n; i++) {
        int t, v, w;
        scanf("%d %d %d", &t, &v, &w);

        if (t == 1) {
            /* 0/1 背包:每个物品只能选一次
               必须从大到小遍历容量,防止同一个物品被重复使用 */
            for (int j = k; j >= v; j--) {
                int val = dp[j - v] + w;
                if (val > dp[j]) {
                    dp[j] = val;
                }
            }
        } else {
            /* 完全背包:物品可无限次选取
               必须从小到大遍历容量,允许多次利用同一物品 */
            for (int j = v; j <= k; j++) {
                int val = dp[j - v] + w;
                if (val > dp[j]) {
                    dp[j] = val;
                }
            }
        }
    }

    printf("%d\n", dp[k]);
    return 0;
}

动态规划(DP)并不仅仅是“刷题”的技巧

它背后蕴含的思想——把一个大问题拆解成若干规模更小、结构相似的子问题,并在子问题答案的基础上进行组合——在工程和建模中都有广泛应用。

在本题中,我们设置一维数组 dp[j] 表示:背包容量为\(j\)时,能够获得的最大价值。初始状态为 dp[0] = 0,其余为 0。每读入一个物品,根据类型决定更新方向:

  • \(t=1\),是 \(0/1\) 背包,容量从大到小枚举 \(j\),保证每个物品至多被使用一次;
  • \(t=0\),是完全背包,容量从小到大枚举 \(j\),允许在同一转移中多次利用该物品。

转移方程在两种情况下都是:
\( dp[j] = \max\bigl(dp[j],\ dp[j - v] + w\bigr), \)
只是在遍历顺序上有所区别。最终输出 dp[k] 即可。

建议大家把这一题当作“混合背包”的模板认真记住,后续遇到更复杂的背包变种时,都会在这个框架上进行扩展。


J:献给挚爱的你的不思议之国

“若十五步以内无法触及彼此,那大概就真的是缘尽于此了。”
——写给所有努力靠近 y 的 x

#include <stdio.h>

#define LIMIT 1000000   /* 状态数值上限,防止乱乘乱加导致越界 */
#define MAXQ 2000000    /* 队列最大长度,足够 15 步以内的 BFS 使用 */

typedef struct {
    int val;
    int step;
} Node;

Node q[MAXQ];
int head = 0, tail = 0;
char vis[LIMIT + 5];

int main(void) {
    int x, y;
    if (scanf("%d %d", &x, &y) != 2) return 0;

    /* 特判:起点就是终点 */
    if (x == y) {
        printf("YES\n");
        return 0;
    }

    /* BFS 起点:从 (x, 0步) 出发 */
    q[tail].val = x;
    q[tail].step = 0;
    tail++;

    while (head < tail) {
        Node cur = q[head++];
        int now = cur.val;
        int step = cur.step;

        if (step > 15) continue;         /* 超过 15 步就不再考虑 */
        if (now < 0 || now > LIMIT) continue;

        if (vis[now]) continue;
        vis[now] = 1;

        if (now == y) {
            printf("YES\n");
            return 0;
        }

        if (step == 15) continue;        /* 15 步已经用完,不能再扩展 */

        /* 4 种操作:都算一步 */

        /* 1:变成 0 */
        if (!vis[0]) {
            q[tail].val = 0;
            q[tail].step = step + 1;
            if (tail < MAXQ) tail++;
        }

        /* 2:乘以 7 */
        long long v1 = (long long)now * 7;
        if (v1 >= 0 && v1 <= LIMIT && !vis[(int)v1]) {
            q[tail].val = (int)v1;
            q[tail].step = step + 1;
            if (tail < MAXQ) tail++;
        }

        /* 3:除以 2 */
        int v2 = now / 2;
        if (v2 >= 0 && v2 <= LIMIT && !vis[v2]) {
            q[tail].val = v2;
            q[tail].step = step + 1;
            if (tail < MAXQ) tail++;
        }

        /* 4:加 1 */
        int v3 = now + 1;
        if (v3 >= 0 && v3 <= LIMIT && !vis[v3]) {
            q[tail].val = v3;
            q[tail].step = step + 1;
            if (tail < MAXQ) tail++;
        }
    }

    printf("NO\n");
    return 0;
}

这个题其实是有一点难度的,作为搜索题,有许多边界条件,但是只要稍作限制就可以了

其实这个题还可以加速1/4,变0操作可以直接放进队列中,注意到,变0操作只执行一次是最优的

执行更多次变0操作一定会浪费步数

关于bfs广度搜索算法

想象你迷路了,站在起点,你不会乱跑,而是:

  1. 先走一步,看四周能到哪
  2. 再从所有“一步能到的地方”同时再走一步
  3. 再从“二步能到的地方”同时再走
  4. 这样一圈、一圈往外扩散

你第一次走到目标时,你一定是 用最少步数 到的,因为你是按步数从小到大扩的。


幕后的幕后

感谢大家对本题解的仔细阅读,本次编写题解的依然是我:

粉紫色系超人气月兔铃仙大人!

相信大家经过十几天的艰难险阻,已经对c语言的理解更加深一个层次了

题目或许不是好题,但是我希望大家能够着眼于题目想要让大家学会的知识

大家看个开心便是

题解编写的时间并没有出题时这么长,主要工作就是把标程整理出来,再补充一些关于出题思路、常见错误和赛后建议。

为了准确性和表达力,我特意花费80r购买一个月的gpt5.1 plus

感觉付费ai确实很好用啊!

题解包里包含所有题的所有数据

题解版试题包内,那些代码基本都是我手搓的,部分使用ai减少工作量,包含标答和数据生成器

因为我经常用c++,所以用c++写了,可以用ai直接转换为c语言版,无伤大雅

请注意,代码文件有部分错误,请以这篇题解的代码为准

本题解中的所有代码,我都在洛谷上重新测试过。

如果发现仍有疏漏,欢迎联系你们的负责人,或者直接联系我(QQ:你知道的太多了)。

那么最终的最终,题解也告一段落,期待明年的这个时候,能再一次为大家出一套题

远方传来风的讯息

必须快点我到我心爱的爱丽丝才行。

因此,前进是必要的。

感觉观看!\([2025/11/22\) \(0:46]\)

posted @ 2025-11-23 22:41  粉紫系超人气月兔铃仙  阅读(9)  评论(0)    收藏  举报