LeetCode| 大数求余:即答案对1e9+7(1000000007)取模原因、方法总结

大数求余原因:大数越界

大数越界:随着n增大,f(n)会超过Int32甚至Int64的取值范围,导致最终的返回值错误。

当一个问题只对答案的正确性有要求,而不在乎答案的数值,可能会需要将取值很大的数通过求余变小。

求余运算规则:

设正整数x,y,p,求余符号为⊙。

对于加法运算: (x+y)⊙p = (x⊙p+y⊙p)⊙p
对于乘法运算: (xy)⊙p = [(x⊙p)(y⊙p)]⊙p

以防x,y本身就超出int32范围,可以创建一个long型变量tmp保存临时结果。

<think>嗯,用户想了解如何有向图上1e9+7的最短路径。首先,我得确定这个问题的具体含义。这里的“1e9+7”可能有两种理解:一种是最短路径的长度在计算过程中需要,另一种可能是边权本身就是后的值。不过通常来说,最短路径算法中的运算通常是在结果上应用,防止数值过大,比如在需要输出答案。但用户提到的是“有向图上mod1e9+7的最短路径”,可能指的是路径权重需要满足某种数条件,比如最短路径长度在1e9+7后的值最小。或者,可能是要路径长度在意义下的最小值,即寻找所有可能路径中,路径长度mod 1e9+7最小的那个。 接下来,我需要考虑不同的情况。如果是常规的最短路径,但最终结果需要,那直接使用Dijkstra或SPFA等算法,计算实际的最短路径,然后对结果即可。但用户的问题可能更复杂,比如要意义下的最小值。例如,可能存在多条路径,其实际长度不同,但1e9+7后可能更小。比如,假设1e9+7是质数,那么可能需要考虑路径长度在这个数后的最小非负值。 不过,这样的问题在传统的最短路径算法中没有直接对应的方法,因为运算会破坏路径长度的可加性结构。比如,a ≡ b mod M,并不一定意味着a + c ≡ b + c mod M,但这里可能用户的问题需要找到路径长度mod M后的最小值,无论实际路径长度的大小,比如希望找到路径长度mod M后最小的非负整数,即使实际路径可能很大,但后更小。 这种情况下,可能需要重新定义状态。例如,在Dijkstra算法中,不仅要记录到达某个节点时的最短距离,还要记录该距离mod M的值。因为可能存在不同的路径到达同一个节点,但它们的mod值不同,而其中某个mod值更小。例如,假设M=7,到达某节点u有两条路径,长度分别为8和15,那么mod7后分别是11,此时可能选择更短的实际长度。但如果另一条路径长度是6,mod7后是6,虽然实际长度更短,但mod后的值更大。所以,用户的问题可能分为两种情况:1. 实际的最短路径,然后输出mod M后的结果;2. 所有路径中mod M后的值最小的那个,即使实际路径长度更长,但mod后更小。 如果是第一种情况,常规的最短路径算法即可,最后。但如果是第二种情况,就需要更复杂的处理。例如,对于每个节点u,维护一个数组dist[u][r],表示到达u时路径长度mod M为r的最小实际长度。然后,通过类似Dijkstra的方式,每次扩展状态时,计算新的mod值,并更新对应的实际长度。 不过,这样的方法可能面临状态数爆炸的问题,因为M是1e9+7,这个数值极大,无法为每个节点维护M个状态。这时候,问题就变得不可行了。所以,这可能意味着用户的问题其实是第一种情况,即实际的最短路径,然后对结果。或者,可能存在某种约束条件,比如边权较小,或者M较小,但用户给出的M是1e9+7,这显然无法处理。 因此,可能需要进一步确认用户的问题。但根据常规情况,用户可能是在实际最短路径,然后,比如在算法竞赛中,为了避免数值过大,通常会要对结果,例如在存在负权边的情况下使用SPFA,或者没有负权边使用Dijkstra,最后结果mod 1e9+7。例如,LeetCode中的某些题目可能会有这样的要。 假设用户的问题属于这种情况,那么回答应该集中在常规的最短路径算法上,并说明最后对结果。例如,对于有向无环图(DAG)且无负权边的情况,使用Dijkstra算法;存在负权边则使用Bellman-Ford或SPFA。然后,结果再。 但用户的问题描述可能更复杂,比如可能存在边权是数后的值,或者需要在计算过程中保持数,这需要不同的处理方式。不过,根据常规情况,最可能的解释是实际最短路径的长度,然后输出mod 1e9+7。因此,回答应该围绕常规的最短路径算法,并最后处理运算。 另外,需要注意1e9+7是一个大质数,通常在编程竞赛中用于避免整数溢出和。因此,可能问题的输入边权已经很大,需要在计算过程中不断,以防止数值溢出,但最终要输出的是实际最短路径的。不过,这在算法过程中是不可能的,因为会改变数值大小,从而影响后续的比较。例如,假设实际路径长度为1e9+8,后为1,而另一条路径长度为2,后为2。此时,正确的做法是选择实际更短的路径,即长度为2的路径,而不是后更小的1e9+8。因此,在计算过程中不能,必须在最后结果处。 因此,正确的步骤是:使用常规的最短路径算法计算实际最短路径的长度,然后对该长度mod 1e9+7。如果最短路径长度可能为负数(存在负权边),则需要先调整到非负数,例如加上M直到结果为正,再。 总结回答的结构应该是: 1. 确定问题类型:实际最短路径,结果。 2. 根据图的情况选择算法:无负权边用Dijkstra,有则用Bellman-Ford或SPFA。 3. 处理结果,1e9+7。 4. 注意可能的溢出问题,在编程中使用大整数类型或边计算边(但仅当不影响实际路径长度比较时,否则不行)。 5. 提供伪代码或步骤说明。 但需要再次确认,在存在负权的情况下,最短路径可能为负数,此时需要处理负数的情况,比如运算后的结果是非负的。例如,-1 mod 1e9+7等于1e9+6。 因此,在回答时需要涵盖这些点,并确保用户了解如何处理不同的情况。</think>要解决有向图上$10^9+7$的最短路径问题,需明确以下两种情况并选择相应方法: --- ### **一、常规最短路径 + 结果** **适用场景**:实际最短路径长度后,再对结果$10^9+7$。 #### **步骤** 1. **选择算法**: - **无负权边**:用Dijkstra算法(时间复杂度$O((V+E)\log V)$)。 - **有负权边**:用SPFA或Bellman-Ford算法(时间复杂度$O(VE)$)。 2. **计算实际最短路径**: - 正常执行最短路径算法,记录到达终点的实际最短距离$d$。 3. **处理**: - 若$d \geq 0$:结果为$d \bmod (10^9+7)$。 - 若$d < 0$:结果为$(d \bmod (10^9+7) + 10^9+7) \bmod (10^9+7)$(确保非负)。 #### **示例代码框架(Dijkstra)** ```python import heapq MOD = 10**9 + 7 def shortest_path_mod(n, edges, start, end): graph = [[] for _ in range(n)] for u, v, w in edges: graph[u].append((v, w)) dist = [float(&#39;inf&#39;)] * n dist[start] = 0 heap = [(0, start)] while heap: d, u = heapq.heappop(heap) if u == end: break if d > dist[u]: continue for v, w in graph[u]: if dist[v] > dist[u] + w: dist[v] = dist[u] + w heapq.heappush(heap, (dist[v], v)) if dist[end] == float(&#39;inf&#39;): return -1 # 不可达 return dist[end] % MOD ``` --- ### **二、意义下的最短路径(特殊需)** **适用场景**:在所有路径中,找到路径长度$10^9+7$后最小的值(即使实际路径更长)。 #### **难点与限制** - 直接维护所有可能的值状态需要$O(V \cdot M)$空间($M=10^9+7$),完全不可行。 - **解决方法**:仅当边权范围较小或问题有特殊约束时,可用动态规划优化(如边权为1)。 #### **替代思路** 如果边权均为**非负整数**且范围较小(如$w \leq 1000$),可定义状态$dp[u][r]$表示到达节点$u$时,路径长度$M$为$r$的最小实际长度。用BFS或优先队列遍历状态。 --- ### **关键总结** 1. **常规需**:用标准最短路径算法,结果。 2. **特殊需**:若需意义下最小,通常因状态数过大无法直接解,需具体问题具体分析。 3. **注意负数处理**:运算需保证结果非负。 若有更具体的约束条件(如边权范围),可进一步优化算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值