
1637:荒岛野人
题目描述
克里特岛以野人群居而著称。岛上有排列成环行的 M 个山洞。这些山洞顺时针编号为 1,2,⋯,M。
岛上住着 N 个野人,一开始依次住在山洞 C1,C2,⋯,CN 中,以后每年,第 i 个野人会沿顺时针向前走 Pi 个洞住下来。每个野人 i 有一个寿命值 Li,即生存的年数。
奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?
输入格式
第一行为一个整数 N,即野人的数目;
第二行到第 N+1 每行为三个整数 Ci,Pi,Li,表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
输出格式
仅包含一个数 M,即最少可能的山洞数。输入数据保证有解,且 M 不大于 106。
样例
样例输入 #1
3
1 3 4
2 7 3
3 2 1
样例输出 #1
6
样例解释 #1
- N=3 个野人。
- 野人 1:初始山洞 C1=1,每年走 P1=3 个洞,寿命 L1=4 年。
- 野人 2:初始 C2=2,每年走 P2=7 个洞,寿命 L2=3 年。
- 野人 3:初始 C3=3,每年走 P3=2 个洞,寿命 L3=1 年。
- 最少需要 M=6 个山洞才能保证任何两个野人在有生之年不会相遇在同一山洞。
- 验证:当 M=6 时,各野人的位置变化(模 6):
- 野人 1:第 t 年位置 (1+3t)mod6,t=0,1,2,3(寿命内)。
- 野人 2:位置 (2+7t)mod6,t=0,1,2。
- 野人 3:位置 (3+2t)mod6,t=0(只活一年)。
- 检查所有 t 组合,没有两个野人在同一年份处于同一山洞。
- 如果 M 更小(如 M=5),则可能出现冲突。
数据范围
对于全部数据:
- 1≤N≤15
- 1≤Ci,Pi≤100
- 0≤Li≤106
时空限制
- 时间限制:1000 ms
- 内存限制:524288 KB
注意:本题需要找到一个最小的 M,使得对于任意两个野人 i 和 j,在它们各自的有生之年(0≤t≤min(Li,Lj))内,不会出现同一年 t 满足:
Ci+Pit≡Cj+Pjt(modM)
即
(Pi−Pj)t≡Cj−Ci(modM)
对每个野人对 (i,j),我们需要确保该方程在 t∈[0,min(Li,Lj)] 内无解(或者解不在该范围内)。
这是一个线性同余方程。设 a=Pi−Pj,b=Cj−Ci,方程 at≡b(modM) 有解的条件是 gcd(a,M)∣b。如果有解,则解的形式为 t≡t0(modM/gcd(a,M))。我们需要确保在 [0,T](其中 T=min(Li,Lj))内没有这样的 t。
由于 N≤15,M 不超过 106,我们可以枚举 M 从 max(Ci) 开始(因为山洞数至少大于等于初始山洞编号的最大值),然后检查是否满足所有野人对都不冲突。检查时,对于每对 (i,j),解方程 at≡b(modM),判断是否存在 t 在 [0,T] 内满足。
具体检查方法:
对于给定的 M,对于每对 i<j:
- 计算 a=Pi−Pj,b=Cj−Ci,T=min(Li,Lj)。
- 方程化为 at≡b(modM)。
- 令 d=gcd(a,M)。
- 如果 bmodd=0,则方程无解,该对不会冲突。
- 否则,方程有解。令 a′=a/d,b′=b/d,M′=M/d。
- 求 a′ 在模 M′ 下的逆元 inv(因为 gcd(a′,M′)=1),则特解 t0=b′⋅invmodM′。
- 通解为 t=t0+kM′,k 为整数。
- 我们需要判断是否存在整数 k 使得 0≤t≤T。即 t0+kM′∈[0,T]。
- 如果存在这样的 k,则冲突,M 不满足条件;否则不冲突。
由于 T 可能很大(Li 可达 106),但 M′ 不会超过 M,我们可以计算最小的非负解 tmin=t0,如果 tmin>T 则无冲突;否则检查 tmin 是否 ≤T,如果是则冲突。但注意通解可能还有更小的解(因为 t0 是模 M′ 意义下的最小非负解,但可能大于 T,然而 t0−M′ 可能是负数,不考虑;或者 t0 本身在 [0,T] 内)。所以只需要检查 t0 是否在 [0,T] 内即可,因为如果 t0 不在范围内,那么其他解 t0+kM′ 要么更大(k>0),要么为负数(k<0),都不在 [0,T] 内。因此,只需判断 0≤t0≤T。
注意:当 a=0 时,方程变为 0⋅t≡b(modM)。如果 b≡0(modM),则对于所有 t 都成立,即任意年份都冲突(除非 T<0 但 T≥0),所以冲突;如果 b≡0(modM),则无解,不冲突。
算法步骤:
- 读入 N 和每个野人的 Ci,Pi,Li。
- 令 M 从 max(Ci) 开始枚举到 106(因为保证有解且 M≤106)。
- 对于每个 M,检查所有野人对 (i,j)(i<j)是否冲突。
- 如果所有对都不冲突,则输出 M 并结束。
由于 N≤15,野人对数最多 105,M 最多 106,检查复杂度 O(N2logM),总计算量大约 105×106×logM 可能太大(108 级别),但实际 M 不会枚举到 106 那么多,因为答案可能较小。可以进一步优化:在检查时,如果发现冲突,立即跳出,枚举下一个 M。另外,由于 M 是山洞数,必须是正整数,且至少为 max(Ci)。
注意:野人的寿命 Li 可能为 0,表示该野人出生即死亡(当年就死),那么只需要检查 t=0 时是否冲突。如果 Li=0,则 min(Li,Lj)=0,只检查 t=0 的情况,即初始位置是否相同。
实现时,注意取模运算可能产生负数,要调整到 [0,M−1]。