标签 数学 下的文章

[collapse status="false" title="Typora 渲染后的 PDF"]https://www.tropical-fish.cn/usr/uploads/2025/12/4031836290.pdf
[/collapse]


abc435

A - Triangular Number 三角数

题面翻译

时间限制:2 秒 / 内存限制:1024 MiB
分数:100 分

题目描述

给定一个正整数 $N$。
输出从 1 到 $N$ 的所有整数的和,即 $1+2+\dots+N$。

约束条件

  • $1 \le N \le 100$
  • $N$ 是整数

输入格式

输入从标准输入按以下格式给出:

N

输出格式

输出从 1 到 $N$ 的所有整数的和。

样例输入 1

5

样例输出 1

15

样例解释 1

因为 $1+2+3+4+5=15$,所以输出 15。

样例输入 2

1

样例输出 2

1

样例输入 3

29

样例输出 3

435

思考

很简单,方法在题面中已经给出了,即 $\sum_{i=1}^{n} i$ ,这个算法的时间复杂度是 $O(n)$ 的。
也可以使用高斯求和的方法, $\frac{n(1+n)}{2}$。
我太懒了,使用高斯求和的方法。

代码

#include <bits/stdc++.h>
using namespace std;
int n,x,i,s;
int main(){
    cin>>n;
    for(i=1;i<=n;i++) s+=i;
    cout<<s;
}

B - No-Divisible Range 无因数区间

题目翻译

时间限制:2 秒 / 内存限制:1024 MiB
分数:200 分

题目描述

给定一个长度为 $N$ 的正整数序列 $A=(A_1,A_2,\dots,A_N)$。
请找出满足 $1 \le l \le r \le N$ 的整数对 $(l,r)$ 的数量,要求这些整数对满足如下条件:
对于所有满足 $l \le i \le r$ 的整数 $i$,$A_i$ 不是区间 $[l,r]$ 内所有元素的和的约数。

约束条件

  • $1 \le N \le 50$
  • $1 \le A_i \le 1000$
  • 所有输入值均为整数

输入格式

输入数据通过标准输入给出,格式如下:

N
A_1 A_2 … A_N

输出格式

输出满足条件的整数对 $(l,r)$ 的数量。

样例输入 1

5
8 6 10 5 7

样例输出 1

6

样例解释 1

序列 $A=(8,6,10,5,7)$。
例如,整数对 $(l,r)=(1,2)$ 满足条件:区间和为 $A_1+A_2=14$,$A_1=8$ 和 $A_2=6$ 都不是 14 的约数。
而整数对 $(l,r)=(1,3)$ 不满足条件:区间和为 $A_1+A_2+A_3=24$,$A_1=8$ 是 24 的约数。
满足条件的整数对为 $(1,2),(1,4),(2,3),(2,4),(3,5),(4,5)$,共 6 个,因此输出 6。

样例输入 2

3
1 1 1

样例输出 2

0

思考

就不打炮打蚊子了。
直接暴力枚举 $l$ 到 $r$,求和为 $S$ ,公式为 $S=\sum_{i=l}^{r} a_i$,然后判断从 $l$ 到 $r$ 如果能被 $S$ 整除,那这个就不是一个无因数区间,不应该计入到答案,否则就计入到答案,最后输出即可。
警告:暴力枚举 $l$ 到 $r$ 的时候,需要排除 $l > r$ 的状态,即 if(l>r) continue;。
时间复杂度为 $O(n^3)$,题目规定 $N \leq 50$,可以通过。

代码

#include <bits/stdc++.h>
using namespace std;
int n,i,a[60],fl,s,t,w,ans;
int main(){
    cin>>n;
    for(i=1;i<=n;i++) cin>>a[i];
    for(t=1;t<=n;t++) for(w=1;w<=n;w++){
        if(t>w) continue;
        fl=1;s=0;
        for(i=t;i<=w;i++) s+=a[i];
        for(i=t;i<=w;i++) if(s%a[i]==0) fl=0;
        ans+=fl;
    }
    cout<<ans;
}

C - Domino 多米诺

题面翻译

时间限制:2 秒 / 内存限制:1024 MiB
分数:300 分

题目描述

有 $N$ 张多米诺骨牌排成一行,放置在数轴上。第 $i$ 张骨牌位于坐标 $i$ 处,高度为 $A_i$。
当第 $i$ 张骨牌向右倒下时,坐标在 $i$ 到 $i+A_i-1$(包含两端)范围内的所有骨牌都会向右倒下。
当第一张骨牌向右倒下时,总共会有多少张骨牌倒下?

约束条件

  • $1 \le N \le 5 \times 10^5$
  • $1 \le A_i \le N$
  • 所有输入值均为整数

输入格式

输入数据通过标准输入给出,格式如下:

N
A_1 A_2 … A_N

输出格式

输出当第一张骨牌向右倒下时,倒下的骨牌总数。

样例输入 1

4
3 1 4 1

样例输出 1

4

样例解释 1

当第一张骨牌向右倒下时,第二张和第三张骨牌也会向右倒下。当第三张骨牌向右倒下时,第四张骨牌也会倒下。

样例输入 2

9
1 4 1 4 2 1 3 5 6

样例输出 2

1

样例解释 2

当第一张骨牌向右倒下时,没有其他骨牌会倒下。

样例输入 3

10
5 4 3 2 1 1 2 3 4 5

样例输出 3

5

思考

数据范围 $N \le 5\times10^5$,暴力模拟每张骨牌的连锁倒下会超时,不能用 $O(N^2)$ 的暴力枚举了,必须用 $O(N)$ 贪心策略。
核心是维护当前最远覆盖位置和遍历边界:

  1. 第一张骨牌倒下的初始覆盖范围是 $1+A[1]-1$,记为 ma,用 tmp 记录当前需要遍历的右边界;
  2. 从第 2 张骨牌开始,在 tmp 范围内遍历,不断更新 ma 为所有骨牌能覆盖的最远位置;
  3. 遍历到 tmp 时,将 tmp 更新为新的 ma,扩展遍历范围;
  4. 最终答案取 ma 和 $N$ 的较小值,避免覆盖范围超出骨牌总数。

小声:我看到时间限制为 2s 的时候以为不用贪心,就用暴力枚举,结果 TLE 了我操,∵数据范围是指数级的,是 $2.5 \times {10}^{11}$,但实际上计算机每秒大约只能做 $10^9$ 次,∴会超时。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=500010;
int a[N],n,i,ma,tmp;
int main(){
    cin>>n;
    for(i=1;i<=n;i++) cin>>a[i];
    if(n==0) return cout<<0,0;
    ma=1+a[1]-1;
    tmp=ma;
    i=2;
    while(i<=tmp&&i<=n){
        if(i+a[i]-1>ma) ma=i+a[i]-1;
        if(i==tmp) tmp=ma;
        i++;
    }
    if(ma>n) cout<<n;
    else cout<<ma;
}

D - Reachability Query 2 可达性查询 2

题面翻译

时间限制:3 秒 / 内存限制:1024 MiB
分数:425 分

题目描述

给定一个有 $N$ 个顶点、$M$ 条边的有向图。顶点编号为 $1$ 到 $N$,第 $i$ 条边是从顶点 $X_i$ 指向顶点 $Y_i$ 的有向边。初始时,所有顶点均为白色。
按顺序处理 $Q$ 个查询,每个查询为以下两种类型之一:

  1. 1 v:将顶点 $v$ 染成黑色。
  2. 2 v:判断从顶点 $v$ 出发,沿着边遍历是否能够到达某个黑色顶点。

约束条件

  • $1 \le N \le 3 \times 10^5$
  • $0 \le M \le 3 \times 10^5$
  • $1 \le Q \le 3 \times 10^5$
  • $1 \le X_i, Y_i \le N$
  • 图中无自环(即 $X_i \neq Y_i$)。
  • 图中无重边(即所有 $(X_i, Y_i)$ 互不相同)。
  • 查询中,$1 \le v \le N$。
  • 所有输入值均为整数。

输入格式

输入数据通过标准输入给出,格式如下:

N M
X_1 Y_1
⋮
X_M Y_M
Q
query_1
⋮
query_Q

其中 query_i 表示第 $i$ 个查询,格式为以下两者之一:

1 v
2 v

输出格式

设第二类查询的数量为 $q$,输出 $q$ 行结果:

  • 对于第 $i$ 个第二类查询,若从顶点 $v$ 能到达黑色顶点,输出 Yes;否则输出 No。

样例输入 1

5 6
1 2
2 3
3 1
4 5
1 4
2 5
5
1 3
2 1
2 4
1 5
2 4

样例输出 1

Yes
No
Yes

样例解释

初始时,给定的图如最左侧的图所示。
第一个查询将顶点 3 染成黑色(如中间的图所示)。
第二个查询中,从顶点 1 可以到达黑色顶点 3,故输出 Yes
第三个查询中,从顶点 4 无法到达任何黑色顶点,故输出 No。
第四个查询将顶点 5 染成黑色(如最右侧的图所示)。
第五个查询中,从顶点 4 可以到达黑色顶点 5,故输出 Yes。

思考

很明显,这是一道图论题,其实我个人做的图论题也不多,我首先感觉是 P3916 图的遍历 - 洛谷 的升级版,多了染色和一些杂七杂八的东西,抽象。
小声:我刚看到每个查询的时候我还以为他考的是并查集。
一个经典的解决动态图可达性问题的方法是使用 bitset 或 分块,但 $N=3 \times 10^5$,bitset 太大($N=3 \times 10^5 \space \text{bits}$ 约 $37.5 \space \text{KB}$ 每个顶点,总共 $N=3 \times 10^5$ 个顶点就是 $10^{10} \space \text{bits} \approx 1.25 \text{GB}$,太特么大了)。
我草比赛怎么结束了?

E - Cover query 覆盖查询

题面翻译

时间限制:2 秒 / 内存限制:1024 MiB
分数:450 分

题目描述

有 $N$ 个单元格从左到右排成一行。
从左数第 $i$ 个单元格($1 \le i \le N$)被称为单元格 $i$。
初始时,所有单元格均为白色。

按顺序处理 $Q$ 个查询。
第 $i$ 个查询($1 \le i \le Q$)的内容如下:

给定两个整数 $L_i$ 和 $R_i$($1 \le L_i \le R_i \le N$)。
将单元格 $L_i, L_i+1, \dots, R_i$ 全部染成黑色。
在此操作中,原本白色的单元格会被染成黑色,原本黑色的单元格保持黑色不变。

操作完成后,求出 $N$ 个单元格中仍为白色的单元格数量。

约束条件

  • $1 \le N \le 10^9$
  • $1 \le Q \le 2 \times 10^5$
  • $1 \le L_i \le R_i \le N$
  • 所有输入值均为整数

输入格式

输入数据通过标准输入按以下格式给出:

N Q
L_1 R_1
L_2 R_2
⋮
L_Q R_Q

输出格式

输出 $Q$ 行。
第 $i$ 行($1 \le i \le Q$)输出第 $i$ 个查询的答案。

样例输入 1

10 5
3 5
8 9
5 8
2 9
6 6

样例输出 1

7
5
3
2
2

样例解释

初始时,10 个单元格从左到右排成一行。

第一个查询将单元格 3、4、5 染成黑色。操作后,白色单元格为 1、2、6、7、8、9、10,共 7 个。
第二个查询将单元格 8、9 染成黑色。操作后,白色单元格为 1、2、6、7、10,共 5 个。
第三个查询将单元格 5、6、7、8 染成黑色。操作后,白色单元格为 1、2、10,共 3 个。
第四个查询将单元格 2 到 9 染成黑色。操作后,白色单元格为 1、10,共 2 个。
第五个查询将单元格 6 染成黑色。操作后,白色单元格仍为 1、10,共 2 个。

因此,按顺序输出 7、5、3、2、2。

样例输入 2

1000000000 1
1 500000000

样例输出 2

500000000

思考

[待补]

F - Cat exercise 猫咪的锻炼

题面翻译

时间限制:2 秒 / 内存限制:1024 MiB
分数:550 分

题目描述

有 $N$ 座猫塔从左到右排成一行,从左数第 $i$ 座猫塔($1 \le i \le N$)的高度为 $P_i$。
其中,序列 $(P_1,P_2,\dots,P_N)$ 是 $(1,2,\dots,N)$ 的一个排列。

从左数第 $i$ 座猫塔和第 $j$ 座猫塔之间的距离定义为 $|i-j|$。

初始时,有一只猫位于高度为 $N$ 的猫塔顶端。
高桥想要锻炼这只猫,方式是重复选择并移除猫塔。

当高桥移除一座猫塔时,猫的移动规则如下:

  1. 若猫不在被移除的猫塔顶端,则猫保持不动。
  2. 若猫在被移除的猫塔顶端,且该猫塔的左侧或右侧至少有一座猫塔存在,则猫会移动到以下目标猫塔:

    • 目标猫塔的范围是:从被移除的猫塔出发,通过重复移动到相邻猫塔能够到达的所有猫塔(不包含被移除的猫塔)。
    • 目标猫塔是上述范围内高度最高的猫塔。
    • 此时,猫的移动距离计入总距离,该距离等于移动前所在猫塔和移动后所在猫塔之间的距离(与移动过程中经过的猫塔高度、数量无关)。
  3. 若猫在被移除的猫塔顶端,且该猫塔的左右两侧都没有猫塔存在,则猫会跳进高桥的怀里,锻炼就此结束。这种情况下,不计入任何移动距离。

注意:被移除的猫塔留下的空位不会被填补。也就是说,初始时从左数第 $i$ 座猫塔的相邻猫塔仅为第 $i-1$ 和第 $i+1$ 座猫塔(若存在),后续不会因为其他猫塔被移除而与非原本相邻的猫塔变成相邻关系。

请你求出,锻炼结束前猫能够移动的最大可能总距离。

约束条件

  • $1 \le N \le 2 \times 10^5$
  • $(P_1,P_2,\dots,P_N)$ 是 $(1,2,\dots,N)$ 的一个排列
  • 所有输入值均为整数

输入格式

输入数据通过标准输入按以下格式给出:

N
P_1 P_2 … P_N

输出格式

输出锻炼结束前猫能够移动的最大可能总距离。

样例输入 1

5
5 3 4 1 2

样例输出 1

5

样例解释 1

初始时,猫塔的高度从左到右依次为 5、3、4、1、2。
下文将从左数第 $i$ 座猫塔($1 \le i \le 5$)简称为猫塔 $i$。
初始时,猫位于猫塔 1 的顶端(高度为 5)。

若高桥按照 1 → 2 → 3 → 5 → 4 的顺序移除猫塔,猫的移动过程如下:

  1. 移除猫塔 1:从猫塔 1 出发,通过重复移动到相邻猫塔可到达的猫塔为 2、3、4、5(不含猫塔 1)。其中高度最高的是猫塔 3(高度为 4),猫移动到该猫塔。
  2. 移除猫塔 2:猫不在该猫塔顶端,保持不动。
  3. 移除猫塔 3:从猫塔 3 出发,可到达的猫塔为 4、5(不含猫塔 3)。其中高度最高的是猫塔 5(高度为 2),猫移动到该猫塔。
  4. 移除猫塔 5:从猫塔 5 出发,可到达的猫塔仅有 4(不含猫塔 5),猫移动到该猫塔。
  5. 移除猫塔 4:猫的左右两侧都没有猫塔,跳进高桥怀里,锻炼结束。

此时,猫的总移动距离为 $|1-3| + |3-5| + |5-4| = 5$。不存在任何一种猫塔移除顺序,能让猫的总移动距离达到 6 或以上,因此输出 5。

样例输入 2

3
1 3 2

样例输出 2

1

样例解释 2

初始时,猫塔的高度从左到右依次为 1、3、2。
下文将从左数第 $i$ 座猫塔($1 \le i \le 3$)简称为猫塔 $i$。
初始时,猫位于猫塔 2 的顶端(高度为 3)。

若高桥按照 2 → 3 的顺序移除猫塔,猫的移动过程如下:

  1. 移除猫塔 2:从猫塔 2 出发,可到达的猫塔为 1、3(不含猫塔 2)。其中高度最高的是猫塔 3(高度为 2),猫移动到该猫塔。
  2. 移除猫塔 3:猫的左右两侧都没有猫塔,跳进高桥怀里,锻炼结束。

此时,猫的总移动距离为 $|2-3|=1$,这是最大可能的总距离。

注意:移除猫塔 2 后,猫塔 1 和猫塔 3 不会被视为相邻。

思考

[待补]

G - Domino Arrangement 多米诺序列

题面翻译

时间限制:2 秒 / 内存限制:1024 MiB
分数:600 分

题目描述

有 $N$ 个单元格从左到右依次编号为 $1$ 到 $N$。初始时,所有单元格均未被涂上任何颜色。

共有 $M$ 种颜色,对于第 $i$ 种颜色,你可以选择单元格区间 $[L_i, R_i]$(即 $L_i, L_i+1, \dots, R_i$)内任意数量的单元格,将其涂为该颜色(可选择涂 0 个、1 个或多个)。

请计算满足以下条件的涂色方案数,并将结果对 $998244353$ 取模:

  • 对于每一个单元格 $i$:

    • 若该单元格被涂上了某一种颜色,则其左侧相邻单元格 $i-1$ 和右侧相邻单元格 $i+1$ 中,恰好有一个 单元格被涂成了与 $i$ 相同的颜色;
    • 特别说明:单元格 $0$ 和 $N+1$ 被视为未被任何颜色涂色(即不存在的单元格)。

约束条件

  • $1 \le N,M \le 5 \times 10^5$
  • $1 \le L_i \le R_i \le N$
  • 所有输入值均为整数

输入格式

输入数据从标准输入按以下格式给出:

N M
L_1 R_1
L_2 R_2
⋮
L_M R_M

输出格式

输出满足条件的涂色方案数(对 $998244353$ 取模)。

样例输入 1

5 2
1 3
1 5

样例输出 1

11

样例解释 1

第 1 种颜色可涂色的单元格范围是 $1,2,3$,第 2 种颜色可涂色的单元格范围是 $1,2,3,4,5$。
满足条件的涂色方案共有 11 种。
image.png

样例输入 2

3 3
1 1
2 2
3 3

样例输出 2

1

样例解释 2

唯一满足条件的方案是:不涂任何单元格(若给任意单元格涂色,都无法满足“恰好一个相邻单元格同色”的条件)。

样例输入 3

500000 10
1 499999
2 499998
3 499997
4 499996
5 499995
6 499994
7 499993
8 499992
9 499991
10 499990

样例输出 3

775503999

补充说明

答案需对 $998244353$ 取模后输出。

思考

[待补]

T1

【题面】T678583 A美丽数 (beauty)

题目描述

小 B 对数字有着独到的见解,他认为一个数是美丽数当且仅当这个数的相邻两位都不相同。

例如12345、12121是美丽数,而123321、11不是美丽数。
现在小B想知道,对于所有满足以下条件的数中,最小的那个数是什么?如果不存在这样的美丽数,则输出-1。

· 对 于i(0≤i≤9), 这个数中是i 的位数一共有ai 个。

· 这个数不能有前导0,即012是不合法的。
有多组测试点,每组测试点现在给你a0~a9, 请你回答小B 的问题。

输入格式

第一行包含一个整数T。

接下来T 行,每行10个整数, a0~a9, 含义如题。

输出格式

输出T, 每行一个整数,表示答案。

输入输出样例 #1

输入 #1

12
6 0 0 0 0 0 0 0 0 5
0 1 0 2 0 0 0 0 0 0
3 0 0 0 2 0 0 1 0 0
0 1 2 3 4 5 6 7 8 9
1 2 0 1 5 0 1 0 0 0
2 1 1 0 1 5 0 0 0 0
6 0 1 0 2 0 0 0 1 0
8 1 0 0 1 0 0 0 0 0
5 2 0 0 2 0 1 0 0 0
3 0 0 0 0 3 0 2 1 1
3 1 0 5 0 0 1 0 0 0
0 1 2 0 0 1 0 1 0 5

输出 #1

-1
313
404070
123234345454565656767676787897979898989898989
1404143464
1505052545
-1
-1
1010404060
5050507879
1303030363
1929295979

说明/提示

对于100%的数据,保证:T≤10,1≤n,ai≤ 10⁵, 其中$n=∑ai(0≤i≤9)$
测试点编号数据范围特殊性质
1~2n≤10无
3~4n≤10³无
5~6无限制A
7~8无限制B
9~10无限制无

A: 保证最多只有2个ai>0。

B: 保证最多只有3个ai>0。

【代码】T678583 A美丽数 (beauty)

#include <bits/stdc++.h>
using namespace std;
int t,i,d,p,m,c,w,l,g,a[11],cnt[11],f;
string s;
bool j(int t,int b=-1){
    int mx=0;
    for(i=1;i<=10;i++){
        if(i-1==b) continue;
        if(cnt[i]>mx) mx=cnt[i];
    }
    return mx\*2<=t+1;
}
int main(){
    cin>>t;
    while(t--){
        for(i=1;i<=10;i++) cin>>a[i];
        m=c=0;l=-1;s="";
        for(i=1;i<=10;i++) m+=a[i];
        if(m==0){cout<<-1<<"\\n";continue;}
        for(i=1;i<=10;i++) if(a[i]>c) c=a[i];
        if(c>(m+1)/2){cout<<-1<<"\\n";continue;}
        for(i=1;i<=10;i++) cnt[i]=a[i];
        for(p=0;p<m;p++){
            f=0;
            for(d=1;d<=10;d++){
                g=d-1;
                if(cnt[d]==0) continue;
                if(g==l) continue;
                if(p==0&&g==0) continue;
                cnt[d]--;
                if(j(m-p-1,g)){
                    s+=char('0'+g);
                    l=g;
                    f=1;
                    break;
                }
                cnt[d]++;
            }
            if(!f){cout<<-1<<"\\n";break;}
        }
        if(f) cout<<s<<"\\n";
    }
}

试题

上海市2025CSP-J十连测Round 7.pdf

大感

我们这一次并没有批分数,所以关于上海市2025CSP-J十连测Round 7的内容我们会分为$Part 1$和$Part 2$
这一次我估计很难

上海市2025CSP-J十连测Round 7 题干

一、单项选择题

共15题、每题2分,共计30分,每题有且仅有一个正确选项。

  1. 如果开始时计算机处于小写输入状态,现在有一只小老鼠反复按照CapsLock、字母键A、字母键S和字母键D的顺序循环按键,即CapsLock、A、S、D、CapsLock、A、S、D……则屏幕上输出的第2025个字符是字母()。
    A. A
    B. S
    C. D
    D. a
  2. 在8位二进制补码中,10101011表示的是十进制下的()。
    A. -85
    B. -43
    C. 43
    D. 85
  3. 给定一个含N个不相同数字的数组,在最坏情况下,找出其中最大或最小的数,至少需要$N-1$次比较操作。则最坏情况下,在该数组中同时找最大与最小的数至少需要()次比较操作。(「」表示向上取整,⌊⌋表示向下取整)
    A. $\left\lceil\frac{3N}{2}\right\rceil - 2$
    B. $\left\lfloor\frac{3N}{2}\right\rfloor - 2$
    C. $2N - 2$
    D. $2N - 4$
  4. 表达式$a*(b+c)-d$的后缀表达形式为()。
    A. $abc d*+-$
    B. $abc+*d-$
    C. $abc*+d-$
    D. $-+*abcd$
  5. 约定二叉树的根节点高度为1。一棵结点数为2025的二叉树最少有()个叶子结点;一棵结点数为2025的二叉树最小的高度值是()。
    A. 1,11
    B. 1,12
    C. 2,11
    D. 2,12
  6. 向一个栈顶指针为$hs$的链式栈中插入一个指针s指向的结点时,应执行()。
    A. $hs \to next = s;$
    B. $s \to next = hs; hs = s;$
    C. $s \to next = hs \to next; hs \to next = s;$
    D. $s \to next = hs; hs = hs \to next$
  7. 2-3树是满足两个条件的树:①所有叶结点到根的路径长度相同;②所有非叶子结点有两个或三个子结点。如果一棵2-3树有10个叶结点,那么它可能有()个非叶结点。
    A. 3
    B. 4
    C. 6
    D. 8
  8. 由四个没有区别的点构成的简单无向连通图的个数是()。
    A. 6
    B. 7
    C. 8
    D. 9
  9. 设含有10个元素的集合的全部子集数为S,其中由7个元素组成的子集数为T,则$\frac{T}{S}$的值()。
    A. $\frac{5}{32}$
    B. $\frac{15}{128}$
    C. $\frac{1}{8}$
    D. $\frac{21}{125}$
  10. 如下图所示,共有13个格子。对任何一个格子进行一次操作,会使得它自己以及与它上下左右相邻的格子中的数字改变(由1变0,或由0变1)。现在要使得所有的格子中的数字都变为0,至少需要()次操作。
    A. 3
    B. 4
    C. 5
    D. 6
  11. 一个1×8的方格图形(不可旋转)用黑、白两种颜色填涂每个方格。如果每个方格只能填涂一种颜色,且不允许两个黑格相邻,共有()种填涂方案。
    A. 8
    B. 55
    C. 56
    D. 64
  12. 设G是有n个结点、m条边($n \leq m$)的连通图,必须删去G的()条边,才能使得G变成一棵树。
    A. $m - n + 1$
    B. $m - n$
    C. $m + n + 1$
    D. $n - m + 1$
  13. 有7个一模一样的苹果,放到3个一样的盘子中,一共有()种放法。
    A. 7
    B. 8
    C. 21
    D. 2187
  14. 若$f_0 = 0$,$f_1 = 1$,$f_{n+1} = \frac{f_n + f_{n-1}}{2}$,则随着i的增大,$f_i$将接近于()。
    A. $\frac{1}{2}$
    B. $\frac{2}{3}$
    C. $\frac{\sqrt{5} - 1}{2}$
    D. 1
  15. 以下是32位机器和64位机器的区别是()。
    A. 显示器不同
    B. 硬盘大小不同
    C. 寻址空间不同
    D. 输入法不同

二、阅读程序

判断题1分,选择题3分,共计40分;判断题正确填T,错误填F。

第1题

int solve1(int n) {
    n++;
    int size = 0;
    int digit[16];
    int pow = 1;
    int s = 0;
    while (n > 0) {
        digit[size] = n % 10;
        size++;
        n /= 10;
        s += pow;
        pow *= 5;
    }
    while (size > 0) {
        --size;
        pow /= 5;
        s += (digit[size] / 2) * pow;
        if (digit[size] % 2 == 0) break;
    }
    return s - 1;
}

int solve2(int n) {
    int s = 0;
    for (int i = 1; i <= n; i += 2) {
        int t = i;
        bool pass = true;
        while (t > 0) {
            int x = t % 10;
            if (x % 2 == 0) {
                pass = false;
                break;
            }
            t /= 10;
        }
        if (pass) s++;
    }
    return s;
}

保证solve1与solve2的参数n是非负整数。

判断题

  1. solve1(11)的返回值为6()。
  2. solve2(12345)的返回值为906()。
  3. 对所有的$n > 0$,必有solve1(n) <= n()。
  4. solve1(0)的返回值为0()。

选择题

  1. 关于solve1(n)与solve2(n)的大小关系,当$n \geq 0$时,下列说法正确的是()。
    A. 必然有solve1(n) < solve2(n)
    B. 必然有solve1(n) == solve2(n)
    C. 只有当n为偶数时,才有solve1(n) = solve2(n)
    D. 只有当n为奇数时,才有solve1(n) == solve2(n)
  2. 若将solve1函数中第一句n++去掉,将solve2函数中for循环的i += 2改为i += 1,则新返回值与原来相比()。
    A. solve1不变,solve2变大
    B. solve1不变,solve2变小
    C. solve1变小,solve2不变
    D. solve1变大,solve2不变
  3. solve1(n)与solve2(n)的时间复杂度为()。
    A. $\Theta(logn)$、$\Theta(logn^2)$
    B. $\Theta(logn)$、$\Theta(n)$
    C. $\Theta(logn)$、$\Theta(nlogn)$
    D. $\Theta(n)$、$\Theta(n^2)$

第2题

int a[maxn];
int b[maxn];
int n, m;
const long long mod = 1000000007;
bool filled[maxn][maxn];
long long mem[maxn][maxn];

long long solve(int i, int j) {
    if (filled[i][j]) return mem[i][j];
    if (i == n) return 1;
    if (j == m) return 1;
    filled[i][j] = true;
    if (a[i] == b[j]) {
        long long sum = solve(i + 1, j) + solve(i, j + 1);
        return mem[i][j] = sum % mod;
    } else {
        return mem[i][j] = (solve(i + 1, j) - solve(i + 1, j + 1)) % mod;
    }
}

int main() {
    std::cin >> n >> m;
    for (int i = 0; i < n; ++i) std::cin >> a[i];
    for (int i = 0; i < m; ++i) std::cin >> b[i];
    std::cout << (solve(0, 0) + mod) % mod << "\n";
}

判断题

  1. 若依次输入数据2 2 1 3 3 1,程序返回的结果是3()。
  2. 如果$n = 0$或$m = 0$,程序返回的结果是1()。
  3. 如果两个序列完全相同,程序返回的结果是$2^n$()。
  4. 输出时,执行solve(0,0)+mod是多余的运算()。

选择题

  1. 该程序的主要功能是()。
    A. 计算两个序列的最长公共子序列的长度
    B. 计算两个序列的公共子序列的数量
    C. 计算两个序列的公共子串的数量
    D. 计算两个序列的相同元素个数
  2. 该程序的时间复杂度为()。
    A. $\Theta(n + m)$
    B. $\Theta(n \cdot m)$
    C. $\Theta(2^{m + n})$
    D. $\Theta(nlogm)$
  3. 当$a[i] = b[j]$时,返回值需要减去solve(i+1,j+1)的原因是()。
    A. 排除重复情况
    B. 排除错误情况
    C. 优化程序的空间效率
    D. 优化程序的时间效率

第3题

long long k;
int n;
int p[20];
bool used[20] = {false};
long long frac[20];

void gen(int i) {
    if (i > n) {
        for (int i = 1; i <= n; ++i) std::cout << p[i] << " ";
        return;
    }
    for (int a = 1; a <= n; ++a) if (!used[a]) {
        if (k <= frac[n - i]) {
            p[i] = a;
            used[a] = true;
            gen(i + 1);
            return;
        } else {
            k -= frac[n - i];
        }
    }
}

int main() {
    n = 1;
    std::cin >> k;
    frac[0] = frac[1] = 1;
    while (k > frac[n]) {
        k -= frac[n];
        frac[n + 1] = frac[n] * (n + 1);
        n++;
    }
    gen(1);
}

判断题

  1. 当输入k为1时候,输出1()。
  2. 当输入k为1000时候,输出1 5 2 4 3()。

选择题

  1. 关于程序输出的序列所满足的性质,错误的是()。
    A. 输出的每个数字各不相同
    B. 输出的数字都在1到n之间
    C. 输出的相邻的数字差距不会超过1
    D. 最先输出的数字在程序中是最先被确定的
  2. 下列说法正确的是()。
    A. 越大的k一定会输出越长的序列
    B. k若是奇数,输出序列的长度一定也是奇数
    C. 程序的时间复杂度为(k!)
    D. gen递归是树形递归
  3. 若程序输出的第一个数字为2,第二数字为4,剩下还有三个数字,则输入的k()。
    A. 最小值是60,最大值是65
    B. 最小值是65,最大值是70
    C. 最小值是70,最大值是75
    D. 最小值是75,最大值是80
  4. 如果使得输出序列出现7,则输入k最少需要()。
    A. 343
    B. 874
    C. 2170
    D. 5040

三、完善程序

单选题,每小题3分,共计30分。

第1题

有一个用户,在连续的n天里,都会收到积分,也会消费积分。积分在获得后的m天内有效(m为一个给定的整数),过期失效。在第i天,用户将会获得$p_i$分,他需要消费$c_i$分。若积分不足,则用掉全部积分后用其他方式消费。消费积分时,先用最早的。当天获取的积分可以当天消费。请计算这个用户一共消费了多少积分。

const int max_size = 100000;
int queue[max_size];
int head = 0;
int tail = 0;

int main() {
    int n, m;
    std::cin >> n >> m;
    int sum = 0;
    for (int i = 0; i < n; ++i) {
        int p, c;
        std::cin >> p >> c;
        queue[_(1)_] = p;
        while (_(2)_) {
            if (_(3)_) {
                queue[head] -= c;
                sum += c;
                c = 0;
            } else {
                int amount = _(4)_;
                c -= amount;
                sum += amount;
            }
        }
        if (_(5)_ > m) {
            head++;
        }
        std::cout << sum << "\n";
    }
}
  1. (1)处应填()。
    A. tail
    B. tail + 1
    C. i + head
    D. tail++
  2. (2)处应填()。
    A. head < tail || c > 0
    B. head < tail || p > 0
    C. head < tail && c > 0
    D. head < tail && p > 0
  3. (3)处应填()。
    A. queue[head] > c
    B. queue[tail] > c
    C. queue[head + 1] > c
    D. queue[tail - 1] > c
  4. (4)处应填()。
    A. queue[head++]
    B. queue[head]
    C. queue[tail--]
    D. queue[tail]
  5. (5)处应填()。
    A. head - tail
    B. tail - head
    C. tail + head
    D. i - head + 1

第2题

给定一个1到n的排列$p_1, p_2, ..., p_n$。请统计排列中所有长度大于等于2的连续子序列的次大数之和。定义$max_2(a_i, a_{i+1}, ..., a_j)$表示从$a_i$开始到$a_j$结束的连续子序列中,排名第二大的数,这个数就是一个连续子序列的次大数之和。题目就是要求:$\sum_{1 \leq i < j \leq n} max_2(a_i, a_{i+1}, ..., a_j)$。solve用于解决这个问题。

int q[maxn];
int prev[maxn];
int next[maxn];

long long solve(int n, int p[]) {
    for (int i = 1; i <= n; ++i) {
        _(1)_;
    }
    p[0] = q[0] = prev[0] = 0;
    p[n + 1] = q[n + 1] = next[n + 1] = n + 1;
    for (int i = 1; i <= n; ++i) {
        int num = _(2)_;
        int prev_num = p[i - 1];
        int next_num = p[i + 1];
        prev[num] = _(3)_;
        next[num] = _(4)_;
    }
    long long sum = 0;
    for (int num = 1; num <= n; ++num) {
        int prev_num = prev[num];
        int prev_prev_num = prev[prev_num];
        int next_num = next[num];
        int next_next_num = next[next_num];
        sum += (long long)num * (q[num] - q[prev_num]) * _(5)_;
        sum += (long long)num * (q[next_num] - q[num]) * _(6)_;
        _(7)_ = prev_num;
        _(8)_ = next_num;
    }
    return sum;
}
  1. (1)处应填()。
    A. $q[p[i]] = i$
    B. $q[i] = p[i]$
    C. $q[i] = i$
    D. $q[p[i]] = p[i]$
  2. (2)(3)(4)处应填()。
    A. p[i],prev_num,next_num
    B. q[i],next_num,prev_num
    C. p[i],next_num,prev_num
    D. q[i],prev_num,next_num
  3. (5)处应填()。
    A. (q[prev_num] - q[prev_prev_num])
    B. (q[next_next_num] - q[prev_num])
    C. (q[next_num] - q[prev_prev_num])
    D. (q[next_next_num] - q[next_num])
  4. (6)处应填()。
    A. (q[prev_num] - q[prev_prev_num])
    B. (q[next_next_num] - q[prev_num])
    C. (q[next_num] - q[prev_prev_num])
    D. (q[next_next_num] - q[next_num])
  5. (7)(8)处应填()。
    A. prev[prev_num],next[next_num]
    B. prev[next_num],next[prev_num]
    C. next[prev_num],prev[next_num]
    D. next[next_num],prev[prev_num]

题目

上海市2025CSP-J十连测Round 5

大感

难度感觉还好,我这次也是拿到了80分的成绩,试卷打印的时候少了第一道完善程序,所以这份试卷的第一道完善程序作废,不得分

错题大纲

一 单项选择

T6

题目:设某算法的计算时间表示为递推关系式$ T(n)=T(n-1)+n $,$ n $为正整数,$ T(0) = 1$则该算法的时间复杂度为( )

A $ O(logn) $
B $ O(nlogn) $
C $ O(n) $
D $ O(n^2)$

这道题,我当时是模拟了一下,模拟的结果是这样的:

T(5)=T(4)+5
T(4)=T(3)+4
T(3)=T(2)+3
T(2)=T(1)+2
T(1)=0

此时,$n$为5,一共做了5次的$T(n)$,则时间复杂度为$O(n)$

但是错了

我估摸着是答案写错了

然后,我们邀请AI:

image.png

给定递推关系式 (T ( n )=T ( n-1 )+n)且 (T ( 0 )=1) ,我们可以通过展开递推式来求解 (T ( n ))的表达式。 展开递推式:

[
\begin{array}{l} T (n) = T (n - 1) + n \ = [ T (n - 2) + (n - 1) ] + n = T (n - 2) + (n - 1) + n \ = [ T (n - 3) + (n - 2) ] + (n - 1) + n = T (n - 3) + (n - 2) + (n - 1) + n \ \vdots \ = T (0) + 1 + 2 + 3 + \dots + n \ \end{array}
]

已知 T(0)=1,所以:

[
T (n) = 1 + \sum_ {k = 1} ^ {n} k = 1 + \frac {n (n + 1)}{2}
]

因此, (T ( n ) = \frac { n ( n + 1 ) } { 2 } + 1。) 当 (n) 很大时, (T(n)) 的主要项是 (\frac{n^2}{2}) ,所以 (T(n) = \Theta (n^2)) ,即时间复杂度为 (O(n^2)) 故正确答案是D (O(n^2)) 。

说人话,就是模拟的数据太小了,建议增加数据模拟值

T10

题目:具有$n$个顶点,$e$条边的图采用邻接表存储结构,进行DFS和BFS的时间复杂度均为( )

A $O(n+e)$
B $O(ne)$
C $O(e^2)$
D $O(n^2)$

我在考试中选了B,那时候我根本不知道邻接表是啥

现在让我们邀请AI

邻接表
邻接表是图的一种高效存储结构,用于表示顶点间的关联关系,尤其适合稀疏图(边数远少于顶点数平方)。
存储方式分两部分:

  1. 顶点表:用数组或链表存储所有顶点信息,每个顶点元素关联一个指针,指向其邻接边的列表。
  2. 邻接边表:为每个顶点建立一个链表,链表节点存储与该顶点直接相连的“邻接顶点索引”及边的权重(无向图/有向图通用)。比如无向图中顶点A连B,A的邻接表含B,B的邻接表也含A;有向图中A→B仅A的邻接表含B。
    相比邻接矩阵,邻接表节省空间,查询顶点邻接边时效率更高,是图论中常用的存储方式。

继续邀请ai分析题目

答案选A:$O(n+e)$
解析:在邻接表存储结构中,DFS(深度优先搜索)和BFS(广度优先搜索)遍历图时,每个顶点都会被访问一次(时间复杂度$O(n)$),同时每条边也会被检查一次(时间复杂度$O(e)$)。
两种算法的总操作次数是顶点访问次数与边检查次数的总和,因此时间复杂度均为$O(n+e)$,适用于有向图和无向图的情况。

所以,选A,说人话:分别遍历点和边

T15

题目:由数字1,1,2,4,8,8所组成的不同的四位数的个数是( )

A 102
B 120
C 560
D 720

考试中,不知道就选C

答案为A
本题有4种情况,他们分别是无重复数字 $A_4^4$共24种、含2个1(无8重复) $C_2^4 \times A_2^3=6 \times 6=36$、含两个8(无1重复) $C_2^4 \times A_2^3=36$、含两个1和两个8 C_2^4=6,综合为102种

二 阅读程序

第一大题

#include<iostream>
int main()
{
    int n, c;
    std::cin >> n >> c;
    long long sum = 0;
    int pre = 1000000000;
    for (int i = 0; i < n; ++i) {
        int a;
        std::cin >> a;
        if (pre > a) {
            pre = a;
        }
        sum += pre;
        pre += c;
    }
    std::cout << sum << "\n";
}

T16

题目:当输入的a全部相等时,程序输出的结果一定等于$n \times a$

我当时考试中填的是正确

当时也没模拟完整

考试后模拟的样例:

input

5 3
3 3 3 3 3

output

45

事实声明,本题为×

第二大题

bool c[max_size][max_size] = {false};
void draw(int size, int x, int y)
{
    if (size == 1)
    {
        c[x][y] = true;
    }
    else
    {
        int half = size / 2;
        draw(half, x + half, y);
        draw(half, x, y + half);
        draw(half, x + half, y + half);
    }
}
void print(int n)
{
    int length = 1 << n;
    draw(length, 0, 0);
    for (int x = 0; x < length; ++x)
    {
        for (int y = 0; y < length; ++y)
        {
            if (c[x][y])
                std::cout << '*';
            else
                std::cout << '.';
        }
        std::cout << "\n";
    }
}

这个代码怎么不完整

T20

题目:在draw的过程中,左上角的四分之一子区域始终不会被绘制

当时我模拟是模拟到这里了

模拟图.jpg

然后也懒得模拟了

如果按照这样的规律下去,那么左上角四分之一区域是会被绘制的

也不懂

估计是我题目理解问题

T24

题目:print(n)的时间复杂度为( )

A $O(n)$
B $O(2^n)$
C $O(3^n)$
D $O(4^n)$

答案为D,考试我选了B

但是deepseek的观点是选C,所以,我们需要注意:[font color="#FF0000"]内容由 AI 生成,请仔细甄别[/font]

T27

题目:程序输出的图形,是沿( )对称图形

A 对角线
B 水平中轴
C 垂直中轴
D 中心镜像

考试我选择C,因为从上面那张目前模拟的地方,选C确实对于模拟没错

but

为什么错了???

也许是模拟错了吧

其实还有另外一张模拟了一张的草稿纸,但被我当作lese扔进垃圾桶了

第三大题

bool valid = true;
std::vector<int> adj[max_node];
bool instack[max_node] = {false};
bool visited[max_node] = {false};
void dfs(int node)
{
    instack[node] = true;
    visited[node] = true;
    for (auto after : adj[node]) {
        if (!visited[after]) {
            visited[after] = true;
            dfs(after);
        } else if (instack[after]) {
            valid = false;
        }
    }
    instack[node] = false;
}
int main()
{
    int n, m;
    std::cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y;
        std::cin >> x >> y;
        adj[x].push_back(y);
    }
    for (int i = 1; i <= n; i++)
    {
        if (!visited[i])
        {
            dfs(i);
        }
    }
    if (valid) {
        std::cout << "Valid\n";
    } else {
        std::cout << "Invalid\n";
    }
}

T34

题目:当输入节点数$n=10^5$,边数$m=2 \times 10^5$时,程序是否能高效运行( )

A 能,$O(n+m)$复杂度
B 不能,$O(nm)$复杂度
C 不能,递归栈溢出
D 取决于图的具体结构

说实话,我考试中都不知道这个代码在干什么,全都是瞎懵的,选择题全队,选择题错了一个,即这个,考试懵了C,因为不知道就选C

让我们的deepseek来分析这道题

???deepseek选C???

小声os:@deepseek: look in my eyes . tell me ? why ? why baby ? why ?

三 完善程序

第一大题

S了
但是让deepseek根据题目写代码

#include <iostream>
#include <vector>
using namespace std;

const int MAX_N = 1005;
const int MAX_M = 1005;

int main() {
    int n, N;
    cin >> n >> N;
    vector<string> P(N);
    for (int i = 0; i < N; ++i) {
        cin >> P[i];
    }
    int Q;
    cin >> Q;

    // 前缀和数组,sum_black[i][j] 表示从(0,0)到(i-1,j-1)的黑格数量
    vector<vector<int>> sum_black(n + 1, vector<int>(n + 1, 0));

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            int pi = (i - 1) % N;
            int pj = (j - 1) % N;
            int black = (P[pi][pj] == 'B') ? 1 : 0;
            sum_black[i][j] = sum_black[i - 1][j] + sum_black[i][j - 1] - sum_black[i - 1][j - 1] + black;
        }
    }

    while (Q--) {
        int A, B, C, D;
        cin >> A >> B >> C >> D;
        // 计算矩形区域内的黑格数量,注意坐标从0开始,转换为前缀和的1-based索引
        int black_count = sum_black[C + 1][D + 1] - sum_black[A][D + 1] - sum_black[C + 1][B] + sum_black[A][B];
        cout << black_count << endl;
    }

    return 0;
}

也不知道对不对

第二大题

#include<iostream>
int len(int n) {
    int length = 0;
    while (n > 0) {
        n /= 10;
        length++;
    }
    return length;
}
void print(int n, char ch) {
    while (n-- > 0) std::cout << ch;
}
int main() {
    int a, b;
    char dummy;
    std::cin >> a >> dummy >> b;
    int p = a;
    int q = b;
    while (a != 0 and b != 0) {
        if (a >= b) a %= b;
        else b %= a;
    }
    int gcd;
    if (____(1)____) gcd = b;
    else gcd = a;
    int i = p / q;
    p %= q;
    p /= gcd;
    q /= gcd;
    if (____(2)____) {
        std::cout << i << "\n";
    } else {
        int i_len = len(i);
        int p_len = len(p);
        int q_len = len(q);
        ____(3)____;
        std::cout << ____(4)____ << "\n";
        if (i != 0) std::cout << i;
        ____(5)____;
        std::cout << "\n";
        ____(6)____;
        std::cout << ____(7)____ << "\n";
    }
}

T44

考试的时候眼瞎了,看错位置了,这个是要输出杠的

完

致谢