The 21st Hunan Provincial Collegiate Programming Contest——2025-湖南省赛-A. Customized Shortest Path 题目 A. 定制最短路(分步 dp 拓展解决这个计数问题)
题目大意
题目描述
给定一个包含 n 个顶点和 m 条边的无向图。第 i 条边连接顶点 ui 和 vi,其初始边权(遍历代价)为 wi。
你可以将所有边的边权同时增加一个非负实数 k。
请问:存在多少条从顶点 1 到顶点 n 的不同路径,使得至少存在一个 k 的值,能够让该路径成为从顶点 1 到顶点 n 的最短路之一?
两条路径被认为是不同的,当且仅当它们包含的边数不同,或者在某一步经过了不同编号的边(即使连接的顶点相同)。
由于答案可能很大,请输出可能成为最短路的不同路径数量对 998244353 取模后的结果。
输入格式
第一行包含一个整数 T(1≤T≤1000),表示测试用例的数量。
每个测试用例的第一行包含两个整数 n 和 m(2≤n≤5000,1≤m≤5000),分别表示图的顶点数和边数。
接下来的 m 行,每行包含三个整数 ui、vi 和 wi(1≤ui,vi≤n,1≤wi≤109),描述了一条连接 ui 和 vi、边权为 wi 的无向边。
保证所有测试用例的 n 之和不超过 5000,m 之和不超过 5000。
输出格式
对于每个测试用例,输出一个整数,表示符合条件的路径数量对 998244353 取模的值。
样例输入
1 | 3 |
样例输出
1 | 4 |
样例解释
以第一个测试用例为例,图中有 3 个顶点和 4 条边。
顶点 1 和 2 之间有两条权值为 1 的平行边。
顶点 2 和 3 之间有两条权值为 1 的平行边。
无论非负实数 k 取何值,从 1 到 3 的最短路径一定由一条连接 1,2 的边和一条连接 2,3 的边组成(共经过 2 条边,总权值为 2+2k)。包含边的组合情况共有 2×2=4 种不同路径,因此答案为 4。
对于第二个测试用例:
有三条从 1 到 5 的主要路径方案:
路径一:直接走边 1↔5,包含 1 条边,初始总权值为 3。当所有边权增加 k 时,该路径的总代价为 3+k。
路径二:依次经过 1↔2↔5,包含 2 条边,初始总权值为 1+2=3。当所有边权增加 k 时,该路径的总代价为 3+2k。
路径三:依次经过 1↔3↔4↔5,包含 3 条边,初始总权值为 1+1+1=3。当所有边权增加 k 时,该路径的总代价为 3+3k。
可以发现,当 k=0 时,这三条路径的总代价都是 3,均能够成为从 1 到 5 的最短路。因此可能的路径总数为 3。
对于第三个测试用例,答案经过相同的逻辑推导,共有 4 条路径有可能在某个 k 值下成为最短路。
思路讲解

1 | vector<ll> mndis(N + 2, INF); |
超出可能成为最小值的那些直线,可以使用凸包 O(n) 的解决,也可以使用 naive 的方法 O(n2) 解决。
1 | vector<Point> hull; |
AC代码
AC
https://qoj.ac/submission/2147487
AC
https://codeforces.com/gym/106139/submission/367332908
1 |
心路历程(WA,TLE,MLE……)
感觉最近的 ai 属于是纯纯傻逼啊,这么简单的 bfs 都不会,非要用 dp,真的是纯纯傻逼,问题是 dp 很难解决这个问题!!!
也不能说是他们的问题。

The 21st Hunan Provincial Collegiate Programming Contest——2025-湖南省赛-D. Box(不难注意到,只有在 3*3 的网格上,对角线操作才可以减少操作数量)
题目大意
题目描述
给定一个 n×m 的初始为空的网格,你可以进行以下两种操作:
-
选择一个格子 (x,y),在其所在的整行和整列的所有空格子中放置小球。
-
选择一个格子 (x,y),在经过该格子的两条对角线的所有空格子中放置小球。

即使一个格子中已经有小球,你依然可以选择该格子进行操作。
你需要求出填满整个网格所需的最少操作次数,并输出对应的具体操作方案。
输入格式
第一行为测试用例数量 T(1≤T≤104)。
每个测试用例包含一行两个整数 n,m(1≤n,m≤103),代表网格的行数和列数。
保证所有测试用例的 n×m 之和不超过 106。
输出格式
对于每个测试用例:
第一行输出最少操作次数 p(1≤p≤n×m)。
随后 p 行,每行输出三个整数 op,x,y(1≤x≤n,1≤y≤m),代表一次操作:
-
当 op=1 时,代表在格子 (x,y) 进行行列的操作;
-
当 op=2 时,代表在格子 (x,y) 进行对角线的操作。
样例数据
1 | Input |
样例解释针对第一组测试数据(3×4 的网格):
最少需要 3 次操作。输出提供的方案如下:
-
第 1 次操作:
2 2 2,对 (2,2) 使用对角线操作。 -
第 2 次操作:
2 2 3,对 (2,3) 使用对角线操作。 -
第 3 次操作:
1 2 4,对 (2,4) 使用行列操作。
这 3 次操作结束后,整个 3×4 的网格均会被小球覆盖。
针对第二组测试数据(2×2 的网格):
最少需要 2 次操作。输出提供的方案如下:
-
第 1 次操作:
1 1 1,对 (1,1) 使用行列操作,此时第 1 行和第 1 列被填满。 -
第 2 次操作:
1 2 2,对 (2,2) 使用行列操作,此时第 2 行和第 2 列被填满。
这 2 次操作结束后,全部 4 个格子均被填满。
思路讲解
赛时这个队友的这个思路,还是很厉害的。
不难注意到,只有在 3*3 的网格上,对角线操作才可以减少操作数量。
1 | void Solve() { |
AC代码
AC
https://codeforces.com/gym/106139/submission/367213905
1 | /** |
心路历程(WA,TLE,MLE……)
The 21st Hunan Provincial Collegiate Programming Contest——2025-湖南省赛-B. Cut ellipse(这种题目就是直接这个仿射变换)
题目大意
题目描述
给定二维平面上的一个标准椭圆方程:
a2x2+b2y2=1
其中 a 和 b 是正实数,分别代表椭圆的半轴。
同时给定平面上的一条直线方程:
y=kx+c
已知该直线一定会将椭圆分割成两个区域,要求计算并输出这两个区域中面积较大的那一部分的面积。
输入格式
第一行包含两个整数 a 和 b(1≤a,b≤103),表示椭圆的两个半轴长。
第二行包含两个整数 k 和 c(∣k∣,∣c∣≤103),定义了直线 y=kx+c。
数据保证直线必定与椭圆相交于两个不同的点。
输出格式
输出一个浮点数,表示椭圆中面积较大那一部分的面积。
你的答案与标准答案的绝对误差或相对误差不超过 10−6 即被视为正确。
样例
输入
1 | 2 3 |
输出
1 | 12.709803500 |
样例解释
在样例中,给定椭圆方程为 22x2+32y2=1,即 4x2+9y2=1。
给定直线方程为 y=x+1。
整个椭圆的面积为 π×a×b=6π≈18.8495559。
直线 y=x+1 穿过该椭圆将其分成两部分,经过计算,这两部分中面积较大的区域面积约为 12.709803500。
思路讲解
椭圆方程 a2x2+b2y2=1,做代换 u=ax,v=by,椭圆变成 u2+v2=1(单位圆)。
直线 y=kx+c 变成 bv=ka⋅u+c,即 v=bkau+bc。
面积缩放关系:这个变换的雅可比行列式是 ab,所以在 (u,v) 平面上算出的面积,乘以 ab 就是椭圆上的面积。
具体而言,雅克比行列式是:
u=ax,v=by
反过来就是 x=au,y=bv。雅可比矩阵是把所有偏导数摆成矩阵:
J=(∂u∂x∂u∂y∂v∂x∂v∂y)=(a00b)
雅可比行列式 = det(J)=ab−0=ab。
这意味着:(u,v) 平面上任何一块面积为 S 的区域,对应回 (x,y) 平面上面积为 ab⋅S。
1 | void Solve() { |
AC代码
AC
https://codeforces.com/gym/106139/submission/367303278
1 | /** |
心路历程(WA,TLE,MLE……)
这个形式一定要化简到 v=u。。。什么的形式
