加载中...

ABC 443 DEFG

D - Pawn Line

赛时是猜出来的,但感觉这道题还需要仔细回味一下,如何证明很重要。

这里直接搬其他博主的思路讲解了:zhihu

pZhqeyV.png
pZhqmLT.png

code

E - Climbing Silver

官解用的是 dp,这里给一个容易理解还好写的做法:直接 bfs + 树状数组模拟整个过程,对每一列倒着维护墙数量的前缀和,在 bfs 过程中动态着删可以删除的墙,复杂度 \(O(n^{2}\log n)\)。具体实现见代码。

code

F - Non-Increasing Number

考虑 \(dp\)

状态定义:\(dp_{r,c}\):在 \(\% n\) 意义下,得到余数为 \(r\),且当前末尾数字是 \(c\),数字的最小位数。

初始时没有任何数字, \(dp_{0,0} = 0\)

状态转移:

\[dp_{(x*10+c')\% n,c'} \leftarrow dp_{x,c} + 1,c' \in [\max(1,c), 9] \]

由转移式可知,这类似于 \(bfs\),因此我们可以直接用队列模拟整个 dp 转移过程,每次从队首弹出的状态值都是最小的(也就是位数最少)。发现当前状态的余数 \(r=0\) 时(\(\% n = 0\),说明是 \(n\) 的倍数),说明找到了最优解。

剩下的就是还原方案,记录整个 bfs 过程中的 dp 转移路径并回溯即可。若无解,则会搜索到所有可能的状态,而总状态数是 \(O(10*n)\) 的,仍然可以直接模拟。具体实现见代码。

summary: 像这种需要找到某个数的倍数作为答案的数位题,一般考虑用余数作为 dp 转移的状态。

code

G - Another Mod of Linear Problem

需要用到类欧几里得算法,对本蒟蒻来说属实超纲了qwq。。。

pZhLzVS.png

那么剩下的问题就是如何在 \(n\) 很大时快速求:

\[\sum_{i=0}^{n} \lfloor \frac{ai+b}{c} \rfloor \]

类欧几里得算法:blog

模板:

typedef __int128 LL;
LL calc(LL a, LL b, LL c, LL n) {
	if(n < 0) return 0;
	if(a == 0) return (b / c) * (n + 1);
	LL n2 = n * (n + 1) / 2;
	if (a >= c || b >= c)
	  return calc(a % c, b % c, c, n) + (a / c) * n2 + (b / c) * (n + 1);
	LL m = (a * n + b) / c;
	if (m == 0) return 0;
	return m * n - calc(c, c - b - 1, a, m - 1);
}

ll Euclid_f(int a, int b, int c, int n){ // 为了避免 a, b 存在负数的情况,需要再套一层
	int ar = (a % c + c) % c;
	int aq = (a - ar) / c;
	int br = (b % c + c) % c;
	int bq = (b - br) / m;
	return 1ll * aq * (1ll * n * (n + 1) / 2) + 1ll * bq * (n + 1) + calc(ar, br, c, n);
}

code

posted @ 2026-02-01 11:04  小橘奏  阅读(6)  评论(0)    收藏  举报