扩欧详解
假设我们有一个方程: a x + b y = c ax+by=c ax+by=c。这里给定了 a , b , c a,b,c a,b,c,要让我们求 ( x , y ) (x,y) (x,y)的一对整数解。保证有解。
首先,为了简化问题,假设 a x + b y = 1 ax+by=1 ax+by=1。于是,我们考虑一种神奇的算法——扩展欧几里得算法。
我们每次递归时,对这个式子进行如下变换:
a
x
+
b
y
=
1
ax+by=1
ax+by=1
b
x
+
(
a
m
o
d
b
)
y
=
1
bx+(a\ mod\ b)y=1
bx+(a mod b)y=1
……
1
x
+
0
y
=
1
1x+0y=1
1x+0y=1(此时容易解得
x
=
1
,
y
=
0
x=1,y=0
x=1,y=0)
现在,我们考虑如何递归上传。即,我们要把 b x + ( a m o d b ) y = 1 bx+(a\ mod\ b)y=1 bx+(a mod b)y=1变成与 a x + b y = 1 ax+by=1 ax+by=1相同的模样。
如何变化呢?这么搞:
b
x
+
(
a
−
⌊
a
b
⌋
b
)
y
=
1
bx+(a-\lfloor \frac a b \rfloor b)y=1
bx+(a−⌊ba⌋b)y=1
b
x
+
a
y
−
⌊
a
b
⌋
b
y
=
1
bx+ay-\lfloor \frac a b \rfloor by=1
bx+ay−⌊ba⌋by=1
a
y
+
b
(
x
−
⌊
a
b
⌋
y
)
ay+b(x-\lfloor \frac a b \rfloor y)
ay+b(x−⌊ba⌋y)=1
所以,我们每次从解得的 ( x , y ) (x,y) (x,y),同时变成 y , x − ⌊ a b ⌋ y y,x-\lfloor \frac a b \rfloor y y,x−⌊ba⌋y即可。
注意,这里的 x x x是上一步的 x x x,所以我们要在把 x x x变成 y y y之前,先存储下 x x x的值。
时间复杂度 O ( l o g 1.618 m a x ( a , b ) ) O(log_{1.618}{max(a,b)}) O(log1.618max(a,b))。
注意,这里的底数并不是 1.618 1.618 1.618,但是这个底数与 1.618 1.618 1.618十分接近;之所以复杂度是这个,是因为 a , b a,b a,b为斐波那契数列中相邻两项的时候是最差情况。
容易扩展到 c ≠ 1 c≠1 c=1的情况,与 g c d ( a , b ) ∣ c gcd(a,b)|c gcd(a,b)∣c的情况。可以发现,这个东西也可以用在逆元,甚至在复杂度允许的情况下可以代替中国剩余定理。注意如果不满足 g c d ( a , b ) ∣ c gcd(a,b)|c gcd(a,b)∣c,这个不等式无解。
线性求逆元详解
首先,请读者注意,这里的 = = =请都看成表示模的"三横杠"。
我们考虑如何线性求 i i i在膜 p p p意义下的逆元。
首先,假设 x x x为 p / i p/i p/i的商, y y y为 p / i p/i p/i的余数,显然有
x i + y = 0 ( m o d p ) xi+y=0(mod\ p) xi+y=0(mod p)
等式两边同时除以 i , y i,y i,y,那么
x y − 1 + i − 1 = 0 ( m o d p ) xy^{-1}+i^{-1}=0(mod\ p) xy−1+i−1=0(mod p)
i − 1 = − x y − 1 ( m o d p ) i^{-1}=-xy^{-1}(mod\ p) i−1=−xy−1(mod p)
i − 1 = − ⌊ p i ⌋ ( p m o d i ) − 1 i^{-1}=-\lfloor \frac p i \rfloor (p\ mod\ i)^{-1} i−1=−⌊ip⌋(p mod i)−1
由于 p m o d i p\ mod\ i p mod i的逆元可以 O ( 1 ) O(1) O(1)调用(已求过),于是,我们学会了线性求逆元。
这只是一个卡常技巧,但是并不超提高组的大纲。虽然从来没有考过
建议大家把这个结论背下来,考场上不用推式子了,直接用。
再书写得明确一点,假设 i n v i inv_i invi表示 i i i的逆元,那么
i n v i = ( p − ⌊ p i ⌋ ) i n v p m o d i inv_i=(p-\lfloor \frac p i \rfloor)inv_{p\ mod\ i} invi=(p−⌊ip⌋)invp mod i
上代码:
a[1]=1;
for (int i=2;i<=n;i++) a[i]=((p-p/i)*a[p%i])%p;
刷题笔记
ACL B
枚举 k k k与 k + 1 k+1 k+1分别能被哪两个积为 n n n的数整除,然后跑几遍扩欧并取最小值即可。
时间复杂度 O ( f ( n ) l o g n ) O(f(n)logn) O(f(n)logn), f ( n ) f(n) f(n)表示 n n n的约数个数。
总结: 慎用变量名, s a v e x savex savex不能用! y 1 y1 y1不能用!!!
(惨