最近学习了同余最短路,过来复习一下。
Question
给定一个线性不定方程
问 \(y∈[0,k]\) 中有多少个 \(y\) 可以被上式表示。
Solution
首先考虑一个简单的。
其中 \(a,b,c\) 是系数,\(x,y,z\) 是变量,\(w∈[0,k]\)。
上式可以理解成有 \(x\) 个 \(a\),\(y\) 个 \(b\),\(z\) 个 \(c\) 组成 \(w\)。现在考虑固定了 \(a\) 前面的系数 \(x\),那么如果我们能够表示出一个数 \(w'\),那么 \(w'+a,w'+2a\dots\) 都能够被表示出来。不妨我们固定 \(x=0\),那么我们要找一个 \(by+cz\) 能够表示出的最小的一个数。
但是如果仅仅是找到一个数,那么我们只能表示其加上若干倍 \(a\) 的数,这些数都与 \(a\) 同余。所以我们用 \(f_i\) 表示 \(by+cz\) 模 \(a\) 为 \(i\) 的最小数即可。
那么怎么找呢?这就来到了同余最短路的精髓所在,图论建模。考虑建 \(a\) 个点,编号为 \(0\dots a-1\),对于编号为 \(i\) 的点,我们可以通过加一个 \(b\),加一个 \(c\) 得到另外的模 \(a\) 的数,所以建立有向边 \(i\) 到 \((i+b)\bmod a\),权值为 \(b\),\(i\) 到 \((i+c)\bmod a\),权值为 \(c\),然后跑一遍最短路就可以得到 \(f_i\) 了。
最后就是统计答案。对于 \(f_i\),我们知道,\(f_i+a,f_i+2a\dots f_i+sa\) 都可以被表示出来。由式子 \(f_i+sa≤k\),可以知道 \(0≤s≤\lfloor \frac{k-f_i}{a} \rfloor\)。所以个数为
注意实际操作中,如果不能表示出模 \(a\) 等于 \(i\) 的数,其 \(f_i\) 的值应该为 \(∞\),统计答案时要注意特判。
讲完三个的情况,那么对于一开始的问题就很简单了。
下面分析一下时间复杂度。总共有 \(N=\min\{d_i\}\) 个点,每一个点连接 \(n-1\) 条边,在一个点数为 \(N\),边数为 \(N\times(n-1)\) 的图上跑 \(dij\),时间复杂度为 \(O(nN\log N)\)。
Practice
题目链接:
P3403 跳楼机
P2662 牛场围栏
P2371 墨墨的不等式
都是同余最短路板子题。
浙公网安备 33010602011771号