欧拉函数 线性筛 快速幂 逆元 中国剩余定理 exgcd

快速幂

快速幂是对倍增思想的应用,可以以 log \log 级别的复杂度求 a k a^k

k k 为偶数,则 a k = a k 2 × a k 2 a^k = a^{\frac{k}{2}} \times a^{\frac{k}{2}}

k k 为奇数,则 a k = a 1 × a k 1 a^k = a^1 \times a^{k-1} 。奇数减一为偶数。

int ksm(int a, int k, int p) {
  	int res = 1;
  	while (k) {
    	if (k & 1) res = res * a % p;
    	a = a * a % p;
    	k >>= 1;
  	}
  	return res % p;
}

线性筛

线性筛质数可求 1 n 1 \sim n 所有的质数。

对于每一个数 i i ,标记所有小于 「 i i 的最小质因子」 的质数 × i \times i 的数为合数。如 i = 77 = 7 × 11 i=77=7 \times 11 ,那么 2 × 77 ,   3 × 77 ,   5 × 77 2 \times 77, \ 3\times 77, \ 5 \times 77 会标记为合数。

想证明该算法为线性且正确,只需证明没有重复筛,没有多筛,没有漏筛三点即可。其中没有重复筛显然成立。

令一个合数 x = j = 1 n p j p j < p j + 1 x = \prod _{j=1}^n p_j \land p_j < p_{j+1}

筛掉该合数的机会为 i = j = 1 n p j p j x = p j × j = 1 n p j p j i = \frac{\prod _{j=1}^n p_j}{p_j} \land x = p_j \times \frac{\prod _{j=1}^n p_j}{p_j} 。因为标记所有小于 「 i i 的最小质因子」 的质数 × i \times i 的数为合数,所以 j = 1 j = 1 。没有重复筛成立。

j = 1 n p j p 1 < x \frac{\prod _{j=1}^n p_j}{p_1} < x ,所以 i = j = 1 n p j p 1 i = \frac{\prod _{j=1}^n p_j}{p_1} 时将 x x 标记为合数。没有漏筛成立。

int pr[N + 5], vis[N + 5] = {1, 1}, n, tot;
void init() {
	for (int i = 1; i <= N; i++) {
		if (!vis[i]) pr[++tot] = i;
		for (int j = 1; j <= tot && i * pr[j] <= N; j++) {
			vis[i * pr[j]] = 1;
			if (i % pr[j] == 0) break; 
		}
	}
} 

exgcd

扩展欧几里得求形如 a x + b y = c ax + by = c 的方程。

  • 对于不为 0 0 的整数 a , b a,b ,存在整数 x , y x,y ,使得 a x + b y = g c d ( a , b ) ax + by = gcd(a,b)

  • 方程 a x + b y = c ax + by = c 有解,当且仅当 g c d ( a , b ) c gcd(a,b)|c

特殊情况:对于 a x + b y = g c d ( a , b ) ax + by = gcd(a,b) ,当 b = 0 b = 0 时,令 x = 1 , y = 0 x = 1, y = 0 即求得一组解。

一般情况:借鉴辗转相除法 g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a,b)=gcd(b,a \bmod b) ,假设已经求得了 ( b m o d a ) x 0 + a y 0 = g c d ( a , b ) (b \bmod a) x_0+ay_0=gcd(a,b) 的一组解 ( x 0 , y 0 ) (x_0, y_0) ,方程可以根据 a m o d m = a m a m a \bmod m=a-m\left \lfloor \frac{a}{m} \right \rfloor 变形为

( b a b a ) x 0 + a y 0 = g c d ( a , b ) (b-a\left \lfloor \frac{b}{a} \right \rfloor)x_0+ay_0=gcd(a,b)

b a x 0 + a y 0 + b x 0 = g c d ( a , b ) \left \lfloor \frac{b}{a} \right \rfloor x_0 + ay_0 + bx_0 = gcd(a,b)

a ( y 0 b a x 0 ) + b x 0 = g c d ( a , b ) a(y_0-\left \lfloor \frac{b}{a} \right \rfloor x_0)+bx_0=gcd(a,b)

交换 x 0 x_0 y 0 y_0
a ( x 0 b a y 0 ) + b y 0 = g c d ( a , b ) a(x_0-\left \lfloor \frac{b}{a} \right \rfloor y_0)+by_0=gcd(a,b)

{ a x + b y = g c d ( a , b ) a ( x 0 b a y 0 ) + b y 0 = g c d ( a , b )       { x = x 0 y 0 b a y = y 0 \begin{cases} ax + by = gcd(a,b) \\ a(x_0-\left \lfloor \frac{b}{a} \right \rfloor y_0)+by_0=gcd(a,b) \end{cases} \iff \begin{cases} x=x_0-y_0\left \lfloor \frac{b}{a} \right \rfloor \\ y=y_0 \\ \end{cases}

int exgcd(int a, int b, int &x, int &y) { 
    if (a == 0) {
        x = 0, y = 1;
        return b;
    }
    int d = exgcd(b % a, a, y, x);
    x -= b / a * y;
    return d;
}

如何求最小正整数解。假设我们求出了
a x 0 + b y 0 = g c d ( a , b ) ax_0+by_0 = gcd(a,b)
的一组解 ( x 0 , y 0 ) (x_0, y_0) 。有解的必要条件为 g c d ( a , b ) c gcd(a,b)|c ,所以令 k = c g c d ( a , b ) k = \frac{c}{gcd(a,b)}
a x + b y = c ax + by = c

a x + b y = k × g c d ( a , b ) ax + by = k \times gcd(a,b)

{ a x k + b y k = g c d ( a , b ) a x 0 + b y 0 = g c d ( a , b )       { x = k × x 0 y = k × y 0       { x = c g c d ( a , b ) × x 0 y = c g c d ( a , b ) × y 0 \begin{cases} a \frac{x}{k} + b \frac{y}{k} = gcd(a,b) \\ ax_0 + by_0 = gcd(a,b) \end{cases} \iff \begin{cases} x = k \times x_0 \\ y = k \times y_0 \end{cases} \iff \begin{cases} x = \frac{c}{gcd(a,b)} \times x_0 \\ y = \frac{c}{gcd(a,b)} \times y_0 \end{cases}

a × c g c d ( a , b ) × x 0 + b × c g c d ( a , b ) × y 0 = c a \times \frac{c}{gcd(a,b)} \times x_0 + b \times \frac{c}{gcd(a,b)} \times y_0 = c

为了求最小整数解,需要把上式的 x 0 x_0 尽可能地减小,如果 x 0 x_0 减小,对应的 y 0 y_0 会增加。所以设 x 0 x_0 减小了 t 0 t_0 y 0 y_0 增加了 t 1 t_1
{ x = x 0 × c g c d ( a , b ) c g c d ( a , b ) × t 0 y = y 0 × c g c d ( a , b ) + c g c d ( a , b ) × t 1 a × x 0 × c g c d ( a , b ) a × c g c d ( a , b ) × t 0 + b × y 0 × c g c d ( a , b ) + b × c g c d ( a , b ) × t 1 = c a × c g c d ( a , b ) × x 0 + b × c g c d ( a , b ) × y 0 = c a × c g c d ( a , b ) × t 0 = b × c g c d ( a , b ) × t 1 t 0 t 1 = b × c g c d ( a , b ) a × c g c d ( a , b ) t 0 t 1 = b a \begin{cases} x = x_0 \times \frac{c}{gcd(a,b)} - \frac{c}{gcd(a,b)} \times t_0 \\ y = y_0 \times \frac{c}{gcd(a,b)} + \frac{c}{gcd(a,b)} \times t_1 \end{cases} \\ \Downarrow \\ a \times x_0 \times \frac{c}{gcd(a,b)} - a \times \frac{c}{gcd(a,b)} \times t_0 + b \times y_0 \times \frac{c}{gcd(a,b)} + b \times \frac{c}{gcd(a,b)} \times t_1 = c\\ \because a \times \frac{c}{gcd(a,b)} \times x_0 + b \times \frac{c}{gcd(a,b)} \times y_0 = c \\ \therefore a \times \frac{c}{gcd(a,b)} \times t_0 = b \times \frac{c}{gcd(a,b)} \times t_1 \\ \frac{t_0}{t_1} = \frac{b \times \frac{c}{gcd(a,b)}}{a \times \frac{c}{gcd(a,b)}} \\ \frac{t_0}{t_1} = \frac{b}{a}

a ( x 0 t 0 ) + b ( y 0 + t 1 ) = c       a ( x 0 t 0 ) + b ( y 0 + a b × t 0 ) a (x_0 - t_0) + b(y_0 + t_1) = c \iff a(x_0 - t_0) + b(y_0 +\frac{a}{b} \times t_0 )

t 0 = b g c d ( a , b ) t_0 = \frac{b}{gcd(a,b)} ,将 x 0 x_0 减到不能再减为止,并考虑 b g c d ( a , b ) < 0 \frac{b}{gcd(a,b)} < 0 的情况需要加上模数再取模。总结公式为
{ x m i n = ( x 0 m o d b g c d ( a , b ) + b g c d ( a , b ) ) m o d b g c d ( a , b ) y m i n = c a × x 0 b \begin{cases} x_{min}=(x_0 \bmod \frac{b}{gcd(a,b)} + \frac{b}{gcd(a,b)}) \bmod \frac{b}{gcd(a,b)} \\ y_{min} = \frac {c – a \times x_0}{b} \end{cases}


逆元

逆元与除法取模有关,具体的,如果 a b m o d m = a × x m o d m \frac{a}{b} \bmod m = a \times x \bmod m ,我们把 x x 叫作 b b 在模 m m 意义下的逆元,记做 b 1 b^{-1} 。有
b × x 1 ( m o d m ) b \times x \equiv 1\pmod{m}

求质数逆元常见的方式是费马小定理。 如果模数 p p 为一个质数,而整数 a a 不是 p p 的倍数,则有
a p 1 1 ( m o d p ) a p 2 a 1 ( m o d p ) a^{p-1} \equiv 1\pmod{p} \\ \Updownarrow \\ a^{p-2} \equiv a^{-1} \pmod{p}
所以 a a 的逆元为 a p 2 a^{p-2}

如果模数 m m 不为质数,但 b b m m 互质,那么可以用扩展欧几里得求逆元。因为扩展欧几里得可以求线性同余方程
b × x 1 ( m o d m ) b × x m o d m = 1 b x + ( m y ) = 1 b \times x \equiv 1\pmod{m} \\ \Updownarrow \\ b \times x \bmod m = 1 \\ \Updownarrow \\ bx + (- my) = 1

exgcd 求解即可。


欧拉函数

欧拉函数的符号为 ϕ \phi ϕ ( n ) \phi(n) 为小于等于 n n n n 互质的数的个数。

对于一个质数 p p 和一个整数 k k ,有
ϕ ( p ) = p 1 ϕ ( p k ) = p k p k k = p k p k 1 \phi(p) = p - 1 \\ \phi(p^k) = p^k - \frac{p^k}{k} = p ^k - p^{k-1}

对于一个数 n n ,将他分解质因数
n = i = 1 k p i a i ϕ ( n ) = ϕ ( i = 1 k p i a i ) = i = 1 k p i a i p i a i 1 = i = 1 k p i a i ( 1 1 p i ) = n × i = 1 k ( 1 1 p i ) n = \prod_{i=1}^k p_i^{a_i} \\ \phi(n) = \phi (\prod_{i=1}^k p_i^{a_i}) = \prod_{i=1}^k {p_i}^{a_i} - {p_i}^{a_i - 1} \\ = \prod_{i=1}^k {p_i}^{a_i} (1 - \frac{1}{p_i}) = n \times \prod_{i=1}^k (1 - \frac{1}{p_i})

以上为欧拉函数的通式。

众所周知,欧拉函数为积性函数,有 ϕ ( a b ) = ϕ ( a ) ϕ ( b ) \phi(ab) = \phi(a)\phi(b) ,其中 a a b b 互质。所以可以用线性筛的方法在求质数表的同时求欧拉函数。需要用到以下性质,其中 p p 为质数

  1. ϕ ( p ) = p 1 \phi(p) = p - 1

  2. p i p|i ,那么 ϕ ( i × p ) = ϕ ( i ) × p \phi(i \times p) = \phi(i) \times p ,证明略。

  3. p ∤    i p \not| \ \ i ,那么 ϕ ( i × p ) = ϕ ( i ) × ( p 1 ) \phi(i \times p) = \phi(i) \times (p-1)

略证:若 p ∤    i p\not| \ \ i ,那么 i i p p 互质,根据积性函数的性质 ϕ ( i × p ) = ϕ ( i ) × ϕ ( p ) = ϕ ( i ) × ( p 1 ) \phi(i \times p) = \phi(i) \times \phi(p) = \phi(i) \times (p - 1)

int pr[N + 5], vis[N + 5] = {1, 1}, phi[N + 5], n, tot;
void init() {
	for (int i = 1; i <= N; i++) {
		if (!vis[i]) {
			pr[++tot] = i;
			phi[i] = i - 1;
		}
		for (int j = 1; j <= tot && i * pr[j] <= N; j++) {
			vis[i * pr[j]] = 1;
			if (i % pr[j] == 0) {
				phi[i * pr[j]] = phi[i] * pr[j];
				break; 	
			}
			phi[i * pr[j]] = phi[i] * (pr[j] - 1);
		}
	}
} 

中国剩余定理

中国剩余定理给出了以下的同余方程组,假设 m 1 m n m_1 \sim m_n 两两互质,求 x x 满足
( S ) : { x a 1 ( m o d m 1 ) x a 2 ( m o d m 2 ) x a n ( m o d m n ) (S): \begin{cases} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \quad \vdots \\ x \equiv a_n \pmod{m_n} \end{cases}
中国剩余定理构造如下

M = i = 1 n m i M = \prod_{i=1}^n m_i M i = M m i M_i = \frac{M}{m_i} t i t_i M i M_i 在模 m i m_i 意义下的乘法逆元,即为 M i × t i 1 ( m o d    m i ) M_i \times t_i \equiv 1(\mod m_i)

方程 ( S ) (S) 的通解公式为
x = k M + i = 1 n a i t i M i x = kM + \sum_{i=1}^n a_it_iM_i
如果 k = 0 k = 0 ,则 x x ( S ) (S) 的最小解。

略证:对于 a i a_i m i m_i ,有
t i M i m o d m i = 1       a i t i M i m o d m i = a i m o d m i t_iM_i \bmod m_i = 1 \iff a_it_iM_i \bmod m_i = a_i \bmod m_i
对于 a j , m j ( j i ) a_j, m_j \quad (j \not= i) ,有 m i M i m_i|M_i 。所以 a j t j M j m o d m i = 0 a_jt_jM_j \bmod m_i = 0

对于 k M kM ,同理 k M m o d m i = 0 kM \bmod m_i = 0

综上所述, x = k M + i = 1 n a i t i M i x = kM + \sum_{i=1}^n a_it_iM_i 为方程 ( S ) (S) 的通解。 k = 0 k = 0 时有最小解。

对于上述式子, t i t_i 可以用 exgcd 求逆元的方法求。因为 m 1 m n m_1 \sim m_n 两两互质 j = 1 n m j \prod_{j=1}^n m_j 在约去 m i m_i 后为 M i M_i 且与 m i m_i 互质。

发布了28 篇原创文章 · 获赞 38 · 访问量 485

猜你喜欢

转载自blog.csdn.net/qq_39984146/article/details/104225965