本文是 NOI 一轮复习的第八篇,主要介绍了数论、线性代数、计算几何和其它数学知识。
 
 
正整数中的数论 
主要是针对素数的研究。
素数与合数 
如果一个数 x ( x ∈ N ) x(x\in\mathbb{N}) x ( x ∈ N )   的约数仅有 1 1 1   和它本身,那么就称 x x x   是质数(素数),特别地,0 0 0   和 1 1 1   不是质数,如果一个自然数不是质数,他就是合数。
可以用线性筛在 O ( n ) O(n) O ( n )   的时间内筛出所有质数,用 O ( r + ( r − l + 1 ) log  ( r − l + 1 ) ) O(\sqrt{r}+(r-l+1)\log(r-l+1)) O ( r  + ( r − l + 1 ) log  ( r − l + 1 ))   的时间筛出区间内的所有质数。
p p p   进赋值序列是刻画正整数的重要方式。可以将正整数表示到 p p p   维空间上。
大质因数 
一个数最多只有一个 ≥ v \ge \sqrt{v} ≥ v    的质数因子,这个思路非常经典。
[NOI2015] 寿司晚宴 。最暴力的做法就是设 f S 1 , S 2 f_{S_1,S_2} f S 1  , S 2     代表两人选的质因数状压后分别为 S 1 , S 2 S_1,S_2 S 1  , S 2   ,发现 n ≤ 500 n\le 500 n ≤ 500  ,比 19 19 19   大的质因数最多出现一次,可以单独记录这个大质因数,然后把每一个有这个大质因数的寿司设为一组,在这一组进行转移时另记 g 1 , g 2 g_1,g_2 g 1  , g 2    分别代表只允许这两个人其中一个吃有这个大质因数的寿司,最后合并答案的时候还要减去最初的 f f f  ,因为两个人都不吃的算了两次。代码 。
整除性 
研究整除相关的数论。
数论分块 
数论分块 。⌊ n i ⌋ \left\lfloor\frac{n}{i}\right\rfloor ⌊ i n  ⌋   只有 O ( n ) O(\sqrt{n}) O ( n  )   中不同的取值,并且每一种取值都是一个连续的区间。
比如光速幂是利用这一点来实现的,这个技巧也可以在 O ( n ) O(\sqrt{n}) O ( n  )   时间内枚举到所有区间。
最经典的应用就是快速计算 ∑ i = 1 n f ( i ) g ( ⌊ n i ⌋ ) \sum_{i=1}^n f(i)g\left(\left\lfloor\frac{n}{i}\right\rfloor\right) ∑ i = 1 n  f ( i ) g ( ⌊ i n  ⌋ )  ,需要 O ( 1 ) O(1) O ( 1 )   计算 ∑ i = l r f ( i ) \sum_{i=l}^{r}f(i) ∑ i = l r  f ( i )  ,然后将 g g g   相同的打包计算。
使得 ⌊ n i ⌋ = ⌊ n j ⌋ \lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor ⌊ i n  ⌋ = ⌊ j n  ⌋   成立的最大满足 i ≤ j ≤ n i\le j\le n i ≤ j ≤ n   的块的右端点为 ⌊ n ⌊ n i ⌋ ⌋ \left\lfloor\cfrac{n}{\left\lfloor\frac{n}{i}\right\rfloor}\right\rfloor ⌊ ⌊ i n  ⌋ n  ⌋  。为什么?令 k = ⌊ n i ⌋ k=\lfloor\frac{n}{i}\rfloor k = ⌊ i n  ⌋  ,可知 k ≤ n i k\le \frac{n}{i} k ≤ i n   ,那么 ⌊ n k ⌋ ≥ i \lfloor\frac{n}{k}\rfloor\ge i ⌊ k n  ⌋ ≥ i  ,所以 j = n i j=\frac{n}{i} j = i n   。时间复杂度 O ( n ) O(\sqrt{n}) O ( n  )  。
欧几里德算法 
辗转相减法可以用来求解两个数的 gcd  \gcd g cd :
int  gcd ( int  a,  int  b)  { 
    if  ( a ==  b)  return  a;  
    if  ( ! a ||  ! b)  return  a |  b;  
    if  ( ! ( a &  1 ) )  { 
        if  ( b &  1 )  return  gcd ( a >>  1 ,  b) ;  
        return  gcd ( a >>  1 ,  b >>  1 )  <<  1 ;  
    } 
    if  ( ! ( b &  1 ) )  return  gcd ( a,  b >>  1 ) ;  
    if  ( a >  b)  return  gcd ( ( a -  b)  >>  1 ,  b) ;  
    return  gcd ( ( b -  a)  >>  1 ,  a) ;  
}  
辗转相减(除)是一个非常重要的结构,出现时往往伴随着与 gcd  \gcd g cd  相关的结论。
类欧几里德算法 
万能欧几里德算法 
数论函数 
定义域为整数的函数是数论函数,一般我们研究数论函数中的积性函数。对于所有积性函数 f f f  ,都有 f ( 1 ) = 1 f(1)=1 f ( 1 ) = 1  。
常见积性函数:
单位函数 ϵ ( n ) = [ n = 1 ] \epsilon(n)=[n=1] ϵ ( n ) = [ n = 1 ]  ,是完全积性函数。 
常数函数 1 ( n ) = 1 1(n)=1 1 ( n ) = 1  ,是完全积性函数。 
恒等函数 id  k ( n ) = n k \operatorname{id}_k(n)=n^k id k  ( n ) = n k  ,是完全积性函数,当 k = 1 k=1 k = 1   时可以省略不写。 
除数函数 σ k ( n ) = ∑ d ∣ n d k \sigma_k(n)=\sum_{d\mid n}d^k σ k  ( n ) = ∑ d ∣ n  d k  。这样的话,σ 0 ( n ) = τ ( n ) \sigma_0(n)=\tau(n) σ 0  ( n ) = τ ( n )  ,σ 1 ( n ) \sigma_1(n) σ 1  ( n )   代表约数和,有 σ k ( n ) = ∏ i = 1 s ( ∑ j = 0 α i p i j k ) = ∏ i = 1 s σ k ( p i α i ) \sigma_k(n)=\prod_{i=1}^s\left(\sum_{j=0}^{\alpha_i}p_i^{jk}\right)=\prod_{i=1}^s\sigma_k(p_i^{\alpha_i}) σ k  ( n ) = ∏ i = 1 s  ( ∑ j = 0 α i   p i jk  ) = ∏ i = 1 s  σ k  ( p i α i   )  。 
欧拉函数,φ ( n ) \varphi(n) φ ( n )   代表 1 ∼ n 1\sim n 1 ∼ n   中与 n n n   互质的数的个数。 
本质不同质因子个数函数 ω ( n ) = ∑ p [ p ∣ n ] \omega(n)=\sum_{p}[p\mid n] ω ( n ) = ∑ p  [ p ∣ n ]  。 
 
线性筛可以计算所有的积性函数(前提是可以快速求出 f ( p k + 1 ) f(p^{k+1}) f ( p k + 1 )  ,只需要记录 l o w low l o w   代表最小质因子的最高次幂:
for  ( int  i =  2 ;  i <=  n;  i++ )  { 
    if  ( ! vis[ i] )  prime[ ++ tot]  =  i,  f[ i]  =  . . . ,  low[ i]  =  i;   
    for  ( int  j =  1 ;  j <=  tot &&  i *  prime[ j]  <=  n;  j++ )  { 
        vis[ i *  prime[ j] ]  =  1 ; 
        if  ( i %  prime[ j]  ==  0 )  {   
            low[ i *  prime[ j] ]  =  low[ i]  *  prime[ j] ; 
            if  ( i ==  low[ i] )  f[ i *  prime[ j] ]  =  . . . ;   
            else  f[ i *  prime[ j] ]  =  f[ i /  low[ i] ]  *  f[ low[ i]  *  prime[ j] ] ;  
            break ;  
        } 
        low[ i *  prime[ j] ]  =  prime[ j] ;  
        f[ i *  prime[ j] ]  =  f[ i]  *  f[ prime[ j] ] ;   
    } 
}  
狄利克雷卷积是数论函数的基本运算。定义:
h ( n ) = ∑ d ∣ n f ( d ) g ( n d ) h(n)=\sum_{d\mid n}f(d)g\left(\frac{n}{d}\right)
 h ( n ) = d ∣ n ∑  f ( d ) g ( d n  ) 
简记为 h = f ∗ g h=f*g h = f ∗ g  。
狄利克雷卷积具有交换律、结合律和分配律。
首先,ϵ ∗ f = f \epsilon*f=f ϵ ∗ f = f  。因此单位函数 ϵ \epsilon ϵ   为狄利克雷卷积的单位元 ,那么就可以定义数论函数的逆元 f − 1 f^{-1} f − 1  ,满足 f ∗ f − 1 = ϵ f*f^{-1}=\epsilon f ∗ f − 1 = ϵ  。
一个 f f f   存在逆元,当且仅当 f ( 1 ) ≠ 0 f(1)\ne 0 f ( 1 )  = 0  ,并且逆元唯一。f = g f=g f = g   的充要条件是 f ∗ h = g ∗ h ( h ( 1 ) ≠ 1 ) f*h=g*h(h(1)\ne 1) f ∗ h = g ∗ h ( h ( 1 )  = 1 )  。这样一来有 g ( n ) = − ∑ d ∣ n , d ≠ n g ( d ) f ( n d ) f ( 1 ) g(n) = -\cfrac{\sum\limits_{d \mid n, d \neq n} g(d)f\left(\dfrac n d\right)} {f(1)} g ( n ) = − f ( 1 ) d ∣ n , d  = n ∑  g ( d ) f ( d n  )   。
积性函数的狄利克雷卷积是积性函数,积性函数的逆元也是积性函数。
以下是一些常用的狄利克雷卷积:
1 ∗ 1 = τ 1*1=\tau 1 ∗ 1 = τ  , 
φ ∗ 1 = id  \varphi *1=\operatorname{id} φ ∗ 1 = id  。 
 
任意数论函数 f f f   卷常数函数 1 1 1   等价于做 f f f   的狄利克雷前缀和 ,即:g = f ∗ 1 , g ( n ) = ∑ d ∣ n f ( d ) g=f*1,g(n)=\sum_{d\mid n}f(d) g = f ∗ 1 , g ( n ) = ∑ d ∣ n  f ( d )  。含义是对每个 n n n   计算给定数论函数在其所因数处的取值和。
将每个数写成无穷序列 a n = { c 1 , c 2 , ⋯   } a_n=\{c_1,c_2,\cdots\} a n  = { c 1  , c 2  , ⋯ }   表示 n = ∏ p i c i n=\prod p_i^{c_i} n = ∏ p i c i    。由于 x ∣ y x\mid y x ∣ y   的充要条件为 a x ( c i ) ≤ a y ( c i ) a_x(c_i)\le a_y(c_i) a x  ( c i  ) ≤ a y  ( c i  )  ,因此 f ∗ 1 f*1 f ∗ 1   可以看成对下标做其无穷序列的高维前缀和。
模板 ,这里是对 a a a   做狄利克雷前缀和,本质上是分组背包,每个质数是一组,每组的体积是 p k p^k p k  ,代码 。
欧拉函数 
欧拉函数,即 φ ( n ) \varphi(n) φ ( n )  ,代表 1 ∼ n 1\sim n 1 ∼ n   中与 n n n   互质的数的个数。
设 n = ∏ p i k i n=\prod p_i^{k_i} n = ∏ p i k i    ,则有:
φ ( n ) = n ∏ ( 1 − 1 p i ) = n ∏ p i − 1 p i \varphi(n)=n\prod(1-\cfrac{1}{p_i})=n\prod \cfrac{p_i-1}{p_i}
 φ ( n ) = n ∏ ( 1 − p i  1  ) = n ∏ p i  p i  − 1  
欧拉反演:n = ∑ d ∣ n φ ( d ) n = \sum_{d\mid n} \varphi(d) n = ∑ d ∣ n  φ ( d )  。
莫比乌斯函数 
我们定义莫比乌斯函数:
μ ( n ) = { 1 , n = 1 , 0 , ∃ d > 1 , d 2 ∣ n , ( − 1 ) ω ( n ) , o t h e r w i s e . \mu(n)=\begin{cases}1,&n=1,\\0,&\exists d>1,d^{2}\mid n, \\(-1)^{\omega(n)},&\mathrm{otherwise}. \end{cases}
 μ ( n ) = ⎩ ⎨ ⎧  1 , 0 , ( − 1 ) ω ( n ) ,  n = 1 , ∃ d > 1 , d 2 ∣ n , otherwise .  
实际上它是在对 N \mathbb{N} N   做容斥。设 g ( n ) = ∑ n ∣ d f ( d ) g(n)=\sum_{n\mid d} f(d) g ( n ) = ∑ n ∣ d  f ( d )  ,已知 g g g  ,要求 f ( 1 ) f(1) f ( 1 )  。f ( 1 ) f(1) f ( 1 )   等于 g g g   在 1 1 1   的倍数处取的取值和,减去质数处的取值和,但是多减了两个质数乘积的地方,因此还要加回来。这就是容斥原理,容斥系数是 ( − 1 ) ω ( n ) (-1)^{\omega(n)} ( − 1 ) ω ( n )  。
它不仅是积性函数,还满足:
∑ d ∣ n μ ( d ) = { 1 , n = 1 , 0 , n ≠ 1. \sum_{d\mid n}\mu(d)=\begin{cases}
1,&n=1,\\
0,&n\neq 1.
\end{cases}
 d ∣ n ∑  μ ( d ) = { 1 , 0 ,  n = 1 , n  = 1.  
上述式子描述的其实是 μ ∗ 1 = ϵ \mu*1=\epsilon μ ∗ 1 = ϵ  ,也就是说 μ \mu μ   是 1 1 1   的逆元。这是莫比乌斯函数最重要的性质,其引出了性质:∑ d ∣ n μ ( d ) = [ n = 1 ] \sum_{d\mid n}\mu(d)=[n=1] ∑ d ∣ n  μ ( d ) = [ n = 1 ]  ,我们可以将这个艾弗森括号转化为和式,这样更加方便计算。两者的转化称之为莫比乌斯反演。
莫比乌斯反演有以下结论:
若 g = f ∗ 1 g=f*1 g = f ∗ 1  ,则 f = g ∗ μ f=g*\mu f = g ∗ μ  。 
若 g ( n ) = ∑ n ∣ d f ( d ) g(n)=\sum_{n\mid d}f(d) g ( n ) = ∑ n ∣ d  f ( d )  ,则 f ( n ) = ∑ n ∣ d μ ( d n ) g ( d ) f(n)=\sum_{n\mid d} \mu\left(\dfrac d n\right) g(d) f ( n ) = ∑ n ∣ d  μ ( n d  ) g ( d )  。这也被称为莫比乌斯变换 ,实际上就是把上面那一条给写出来。 
由于 φ ∗ 1 = id  \varphi * 1 = \operatorname{id} φ ∗ 1 = id  ,因此 id  ∗ μ = φ \operatorname{id} * \mu =\varphi id ∗ μ = φ  。 
 
一个常见的应用是,[ gcd  ( i , j ) = 1 ] = ∑ d ∣ gcd  ( i , j ) μ ( d ) [\gcd(i,j)=1]=\sum_{d\mid \gcd(i,j)}\mu(d) [ g cd( i , j ) = 1 ] = ∑ d ∣ g c d ( i , j )  μ ( d )  。虽然看起来这像是废话,但这一步将 i , j i,j i , j   互质转化为了枚举 gcd  ( i , j ) \gcd(i,j) g cd( i , j )   的约数 d d d  。如果 i , j i,j i , j   同样需要枚举,那么枚举 d d d   并计算合法的 i , j i,j i , j   个数(当且仅当 d ∣ i , d ∣ j d\mid i,d\mid j d ∣ i , d ∣ j  )即可。具体来说:
∑ i = 1 n ∑ j = 1 m [ gcd  ( i , j ) = 1 ] = ∑ i = 1 n ∑ j = 1 m ∑ d ∣ gcd  ( i , j ) μ ( d ) = ∑ d = 1 min  ( n , m ) μ ( d ) ∑ i = 1 n ∑ j = 1 m [ d ∣ i ∧ d ∣ j ] = ∑ d = 1 min  ( n , m ) μ ( d ) ⌊ n d ⌋ ⌊ m d ⌋ \begin{aligned}
\sum\limits_{i = 1} ^ n \sum\limits_{j = 1} ^ m [\gcd(i, j) = 1] & = \sum\limits_{i = 1} ^ n \sum\limits_{j = 1} ^ m \sum\limits_{d\mid \gcd(i, j)} \mu(d) \\
& = \sum\limits_{d = 1} ^ {\min(n, m)} \mu(d) \sum\limits_{i = 1} ^ n \sum\limits_{j = 1} ^ m [d\mid i\land d\mid j] \\
& = \sum\limits_{d = 1} ^ {\min(n, m)} \mu(d) \left\lfloor \dfrac n d \right\rfloor \left\lfloor \dfrac m d \right\rfloor \\
\end{aligned}
 i = 1 ∑ n  j = 1 ∑ m  [ g cd( i , j ) = 1 ]  = i = 1 ∑ n  j = 1 ∑ m  d ∣ g c d ( i , j ) ∑  μ ( d ) = d = 1 ∑ m i n ( n , m )  μ ( d ) i = 1 ∑ n  j = 1 ∑ m  [ d ∣ i ∧ d ∣ j ] = d = 1 ∑ m i n ( n , m )  μ ( d ) ⌊ d n  ⌋ ⌊ d m  ⌋  
就可以直接使用数论分块在 O ( n + m ) O(\sqrt{n}+\sqrt{m}) O ( n  + m  )   的时间内计算。
杜教筛 
我们要求积性函数 f f f   的前缀和,设 S ( n ) = ∑ i = 1 n f i S(n)=\sum_{i=1}^{n}f_i S ( n ) = ∑ i = 1 n  f i   ,再找一个积性函数 g g g  ,考虑它们的狄利克雷卷积的前缀和:
∑ i = 1 n ∑ d ∣ i f ( d ) g ( i d ) = ∑ d = 1 n g ( d ) ∑ i = 1 ⌊ n d ⌋ f ( i ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) \begin{aligned}
&\sum_{i=1}^{n} \sum_{d\mid i} f(d)g\left(\frac i d\right)\\
=&\sum_{d=1}^n g(d)\sum_{i=1}^{\left\lfloor\frac n  d\right\rfloor} f(i)\\
=&\sum_{d=1}^n g(d)S\left(\left\lfloor\frac n  d\right\rfloor\right)
\end{aligned}
 = =  i = 1 ∑ n  d ∣ i ∑  f ( d ) g ( d i  ) d = 1 ∑ n  g ( d ) i = 1 ∑ ⌊ d n  ⌋  f ( i ) d = 1 ∑ n  g ( d ) S ( ⌊ d n  ⌋ )  
而我们有:
g ( 1 ) S ( n ) = ∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) \begin{aligned}
g(1)S(n)&=\sum \limits _{i=1}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor)\\
&=\sum\limits_{i=1}^{n}(f*g)(i) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor)
\end{aligned}
 g ( 1 ) S ( n )  = i = 1 ∑ n  g ( i ) S (⌊ i n  ⌋) − i = 2 ∑ n  g ( i ) S (⌊ i n  ⌋) = i = 1 ∑ n  ( f ∗ g ) ( i ) − i = 2 ∑ n  g ( i ) S (⌊ i n  ⌋)  
时间复杂度为 O ( n 3 4 ) O(n^{\frac 3 4}) O ( n 4 3  )  ,我们先线性筛出前 m m m   个的答案,那么 m = n 2 3 m=n^{\frac 2 3} m = n 3 2    时,时间复杂度为 O ( n 2 3 ) O(n^{\frac 2 3}) O ( n 3 2  )  。
模板 。有 μ ∗ 1 = ϵ , φ ∗ 1 = id  \mu * 1 =\epsilon,\varphi * 1 =\operatorname{id} μ ∗ 1 = ϵ , φ ∗ 1 = id  ,那么直接杜教筛即可。代码 。
Min_25 筛 
例题 
巩固一些基础内容。
[CF1656H] Equal LCM Subsets 
Portal .
从质因数幂次的角度考虑,思考哪些是集合中不能要的地雷。
如果 a i a_i a i    不能留在集合中,那么它至少有一个质因子的幂次比 b b b   中其它所有数都大。也就是说,如果 gcd  a i gcd  ( a i , b j ) > 1 \gcd \cfrac{a_i}{\gcd(a_i,b_j)}>1 g cdg cd( a i  , b j  ) a i   > 1  ,那么 a i a_i a i    就该被从集合中删除。相当于单点修改,查询全局 gcd  \gcd g cd ,这个过程只能进行 O ( n + m ) O(n+m) O ( n + m )   轮,线段树直接维护,每轮修改是 O ( ( n + m ) log  ( n + m ) ) O((n+m)\log (n + m)) O (( n + m ) log  ( n + m ))   的,可以接受。代码 。
* [Luogu P5435] 基于值域预处理的快速 GCD 
Portal .
模意义下的数论 
尽管数论相关的题目似乎已经退出环境,但是本身还是比较有意思的。
拉格朗日定理 :在模 p p p   意义下,最高次项系数非 0 0 0   的 n n n   次多项式至多有 n n n   个根。
线性同余方程组 
可以使用 CRT 解决模数互质的情况,exCRT 解决模数不互质的情况。
{ x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) ⋯ x ≡ a 3 ( m o d m 3 ) \begin{cases}
x\equiv a_1 \pmod {m_1}\\
x\equiv a_2 \pmod {m_2}\\
\cdots\\
x\equiv a_3 \pmod {m_3}\\
\end{cases}
 ⎩ ⎨ ⎧  x ≡ a 1  ( mod m 1  ) x ≡ a 2  ( mod m 2  ) ⋯ x ≡ a 3  ( mod m 3  )  
模数互质 
设 M = ∏ i = 1 n m i , M i = m ÷ m i M=\prod_{i=1}^{n}m_i,M_i=m\div m_i M = ∏ i = 1 n  m i  , M i  = m ÷ m i   ,t i t_i t i    是线性同余方程 M i t i ≡ 1 ( m o d m i ) M_it_i\equiv 1 \pmod{m_i} M i  t i  ≡ 1 ( mod m i  )   的一个解,也就是说 t i t_i t i    是 M i M_i M i    模 m i m_i m i    的逆元(显然 M i ⊥ m i M_i \perp m_i M i  ⊥ m i    当且仅当 m i m_i m i    两两互质),那么 x = ∑ i = 1 n a i M i t i + k M x=\sum_{i=1}^{n}a_iM_it_i + kM x = ∑ i = 1 n  a i  M i  t i  + k M  ,最小非负整数解需要求 ∑ i = 1 n a i M i t i   m o d   M \sum_{i=1}^{n}a_iM_it_i\bmod M ∑ i = 1 n  a i  M i  t i  mod M  。
i64 CRT ( void )  { 
    
    i64 ans =  0 ,  x; 
    for  ( int  i =  1 ;  i <=  n;  ++ i)  { 
        M[ i]  =  mm /  m[ i] ;  
        t[ i]  =  inv ( M[ i] ,  m[ i] ) ;  
        ans =  ( ans +  a[ i]  *  M[ i]  *  t[ i] )  %  mm; 
    } 
    return  ( ans %  mm +  mm)  %  mm;  
}  
模数不互质 
考虑如何合并两个方程组。我们先假定一定可以合并,然后看看什么时候合并之后的解是 ∅ \varnothing ∅  。
这玩意儿等价于 a = k 1 m 1 + r 1 = k 2 m 2 + r 2 ⟹ k 1 m 1 − k 2 m 2 = r 2 − r 1 a=k_1m_1+r_1=k_2m_2+r_2 \Longrightarrow k_1m_1-k_2m_2=r_2-r_1 a = k 1  m 1  + r 1  = k 2  m 2  + r 2  ⟹ k 1  m 1  − k 2  m 2  = r 2  − r 1   。这个熟悉!二元一次不定方程!直接使用 exgcd 计算即可。
于是:
如果 gcd  ( m 1 , m 2 ) ∣ ( r 2 − r 1 ) \gcd(m_1,m_2)\mid (r_2-r_1) g cd( m 1  , m 2  ) ∣ ( r 2  − r 1  )  ,那么可以合并; 
否则,exCRT 是无解的。 
 
现在有引理:合并之后的模数是原来两个模数的 lcm。
具体来说,设当前合并的余数为 M M M  ,当前答案为 a n s ans an s  ,那么任意一个 a n s + M x ans+Mx an s + M x   都满足答案,我们需要找到一个最小的 x x x   使得 a n s + M x ≡ a i ( m o d m i ) ans+Mx\equiv a_i\pmod {m_i} an s + M x ≡ a i  ( mod m i  )  ,可以使用扩展欧几里得来解决。
i64 exCRT ( void )  { 
    
    i64 M =  1 ,  ans =  0 ;  
    for  ( int  i =  1 ;  i <=  n;  ++ i)  { 
        i64 b =  B[ i] ,  x,  y,  c =  ( A[ i]  -  ans +  b)  %  b; 
        i64 g =  exgcd ( M,  b,  x,  y) ;  
        if  ( c %  g !=  0 )  return  - 1 ; 
        x =  ( __int128) x *  ( c /  g)  %  ( b /  g) ; 
        ans =  ans +  M *  x; 
        M =  b /  g *  M; 
        ans %=  M;  
    } 
    return  ( ans %  M +  M)  %  M; 
}  
如果模数不是质数,那么可以使用 exCRT 合并。
阶与原根 
例题 
巩固一些基础内容。
[CF1848E] Vika and Stone Skipping 
Portal .
如果跳 g g g   次,需要满足:
2 x ∏ X i = ( 2 f − g + 1 ) g 2x\prod X_i=(2f-g+1)g
 2 x ∏ X i  = ( 2 f − g + 1 ) g 
求的就是 2 x ∏ X i 2x\prod X_i 2 x ∏ X i    的奇因数个数。提前将 x x x   除掉其 lowbit  \operatorname{lowbit} lowbit   即可直接统计其因数。
直接维护即可。注意模数过小时逆元的爆炸问题。代码 。
[NOI2018] 屠龙勇士 
Portal .
由于我们选择的武器是固定的,所以实际上依然是 exCRT,只不过方程换成了 b x ≡ a ( m o d p ) bx\equiv a\pmod p b x ≡ a ( mod p )  。这样是一样的,设当前合并的模数为 M M M  ,答案为 a n s ans an s  ,那么下一个合并要满足 b ( a n s + M x ) ≡ a ( m o d p ) b(ans+Mx)\equiv a\pmod p b ( an s + M x ) ≡ a ( mod p )  ,也就是 b M x − p y = a − b × a n s bMx-py=a-b\times ans b M x − p y = a − b × an s  。
注意一个细节:解出来的解必须能将龙打掉,也就是能将血打成小于等于 0 0 0  ,否则即使满足同余方程也没用。记录一个能把血量打成负数的最小攻击次数,然后如果答案小于这个攻击次数,答案就加上还需要打的次数。代码 。
[CF338D] GCD Table 
Portal .
首先如果有解,那么那个 x x x   应该满足 lcm  ( a 1 , a 2 , ⋯   , a k ) ∣ x \operatorname{lcm}(a_1,a_2,\cdots,a_k) \mid x lcm ( a 1  , a 2  , ⋯ , a k  ) ∣ x  。实际上 x x x   就应该等于 lcm  \operatorname{lcm} lcm  ,因为如果增加倍数,y y y   的构造只会变得更加困难。
这样我们只需要满足 a i ∣ y + i − 1 a_i\mid y+i-1 a i  ∣ y + i − 1  ,exCRT 求一下即可。代码 。
线性代数 
概念 
高斯消元法 
我们可以使用高斯消元以 O ( n 3 ) O(n^3) O ( n 3 )   的时间求解方程组的解。具体来说就是一个一个地加减消元,转化成上三角形式,然后再代入即可。
线性基 
对于异或线性基,我们使用贪心法构建:
void  insert ( i64 x)  { 
    for  ( int  i =  50 ;  i >=  0 ;  -- i) 
        if  ( x &  ( 1ll  <<  i) )  { 
            if  ( ! p[ i] )  {  p[ i]  =  x;  ++ cnt;  break ;  } 
            else  x ^=  p[ i] ; 
        } 
} 
i64 askmx ( void )  { 
    i64 ans =  0 ; 
    for  ( int  i =  50 ;  i >=  0 ;  -- i) 
        if  ( ( ans ^  p[ i] )  >  ans)  ans ^=  p[ i] ; 
    return  ans; 
}  
最小异或值是 min  { p i } \min\{p_i\} min { p i  }  。
线性基的合并直接暴力合并即可。
LGV 引理 
对于一个 DAG,
简单计算几何 
数学杂项 
连分数 
群论入门 
博弈论 
博弈论主要研究一些有竞争或对抗性质的对象,在一定规则下/产生的各种行为。
对于公平组合游戏,我们通常会选择计算 SG 函数;对于非公平游戏,我们会选择推导一些性质。
概念 
我们从 Nim 游戏开始研究。有 n n n   堆石子,每人每次可从任意一堆石子里取出正整数枚石子扔掉,谁不能动谁就输了。
我们将每个状态视作一个节点,那么博弈情况就可以刻画成一张有向图。不难发现,异或和为 0 0 0   时先手必败。
大部分的公平组合游戏(所有玩家都可以操作对方能操作的东西)都可以转换为有向图游戏,对于状态 x x x   和它的 k k k   个后继状态 y 1 , ⋯   , y k y_1,\cdots,y_k y 1  , ⋯ , y k   ,定义 SG 函数为:
SG  ( x ) = mex  { SG  ( y 1 ) , SG  ( y 2 ) , … , SG  ( y k ) } \operatorname{SG}(x)=\operatorname{mex}\{\operatorname{SG}(y_1), \operatorname{SG}(y_2), \ldots, \operatorname{SG}(y_k)\}
 SG ( x ) = mex { SG ( y 1  ) , SG ( y 2  ) , … , SG ( y k  )} 
对于由 n n n   个有向图游戏组成的组合游戏,当且仅当 ⊕ SG  ( s ) ≠ 0 \oplus \operatorname{SG}(s)\ne 0 ⊕ SG ( s )  = 0   的时候,先手必胜,称之为 P 态。也就是说,SG  ( x ) = 0 \operatorname{SG}(x)=0 SG ( x ) = 0   是必败态 ,称之为 N 态。
SG 定理 :一个游戏的 SG 值是其所有子游戏的 SG 值的异或和,这可以说明 Nim 游戏结论的由来。
[HNOI2007] 分裂游戏 。终止状态是所有豆子在 n n n   号瓶子,而每个豆子是独立的,直接暴力 DP 即可。代码 。
Anti-SG 定理 
如果不能动的人获胜,那么这个游戏叫做反常游戏。同样的,有判断必胜条件的 Anti-SG 定理:
如果游戏的 SG 值为 0 0 0  ,那么所有子游戏的 SG 值都不超过 1 1 1   时先手必胜(还是要异或值为 0 0 0  ); 
如果游戏的 SG 值不是 0 0 0  ,那么至少有一个子游戏的 SG 值超过 1 1 1   时先手必胜。其在决策过程中可以转化为上述情况。 
 
模板 。
经典博弈模型 
博弈论中有一些特别经典的问题,我们来介绍一些。
威佐夫博弈 
Portal .
两堆石子,可以取一堆中的任意个,也可以在两堆中都取 x x x   个。
 
我们可以发现以下状态是先手必败的:
( 0 , 0 ) (0, 0) ( 0 , 0 )  , 
( 1 , 2 ) (1, 2) ( 1 , 2 )  , 
( 3 , 5 ) (3, 5) ( 3 , 5 )  , 
( 4 , 7 ) (4, 7) ( 4 , 7 )  , 
( 6 , 10 ) (6, 10) ( 6 , 10 )  , 
( 8 , 13 ) (8, 13) ( 8 , 13 )  。 
 
两者的差是自然数列,第一个数是之前所有新出现的数是之前出现数的 mex。可以证明结论是 a = ⌊ ( b − a ) × 5 + 1 2 ⌋ a=\left\lfloor (b-a)\times \cfrac{\sqrt{5}+1}{2}\right\rfloor a = ⌊ ( b − a ) × 2 5  + 1  ⌋   时先手必败。
公平组合 
博弈论除了 SG 定理外,剩下的内容几乎全部基于 DP。有时候通过打表来寻找 SG 函数的规律也是一个不错的选择。
[CF768E] Game of Stones 
Portal .
可以考虑一个石堆会被取多少次,发现是从 1 1 1   开始依次取,然后就转成了正常的 Nim 游戏。代码 。
[HNOI2014] 江南乐 
Portal .
考虑枚举所有的 m m m  ,那么可以计算所有 n n n   的 SG 值。发现整除分块可以优化枚举 m m m   这个过程,因为 n / m n/m n / m   和 n / m + 1 n/m+1 n / m + 1   必有一个奇偶性不变。代码 。
[AGC017D] Game on Tree 
Portal .
问题可以分解成若干棵子树,每棵子树都带着根节点,然后发现其 SG 值是子树的 SG 值加 1 1 1  ,直接处理即可。代码 。
[AGC010D] Decrementing 
Portal .
如果初始 ∑ a i − 1 \sum a_i-1 ∑ a i  − 1   为奇数,那么先手可以一直维持这个状态(只需要操作偶数即可,情况不会改变)。
初始为偶数呢?如果局面下只有一个奇数,那么操作它就可以出现偶公因数,模拟即可。代码 。
[AGC016F] Games on DAG 
Portal .
不难想到按照 SG 值进行分层转移,对于新增加的 SG 值更小的部分,一定要有边连向它们中的点来保证 SG 值的大小。转移的时候直接枚举子集 S S S  ,判断到达的 SG 值更小的集合 T T T  ,此时令 SG  ( T ) = k \operatorname{SG}(T)=k SG ( T ) = k  ,设 f i f_i f i    代表考虑集合 i i i   中的点时 SG  ( 1 ) = SG  ( 2 ) \operatorname{SG}(1)=\operatorname{SG}(2) SG ( 1 ) = SG ( 2 )   的方案数,转移:
对于 T → S T\rightarrow S T → S   的边,每一个 T T T   中的元素都至少向 S S S   中连一条边; 
对于 S → T S\rightarrow T S → T   的边,随便连即可。 
 
直接做即可。代码 。
[ABC278G] Generalized Subtraction Game 
Portal .
如果可以先手第一步下在中间,然后我们就下模仿棋就行了。
否则,此时选择的区间长度固定,考虑计算 SG 函数,令 SG  i \operatorname{SG}_i SG i    代表长度为 i i i   的游戏的 SG 值。
对于 i < l i<l i < l  ,有 SG  i = 0 \operatorname{SG}_i=0 SG i  = 0  ,否则枚举选择的长度,有 SG  i = mex  j = 0 i − l { SG  j xor  SG  i − j − l } \operatorname{SG}_i=\operatorname{mex}_{j=0}^{i-l}\{\operatorname{SG}_{j} \operatorname{xor} \operatorname{SG}_{i-j-l}\} SG i  = mex j = 0 i − l  { SG j  xor SG i − j − l  }  。
输出方案时采用 set 维护连续段,不断选择后手必败的区间即可。
[CF1458E] Nim Shortcuts 
Portal .
正常情况下,黑色的是先手必败的:
但如果存在限制(黄色的也是必败态,那么情况会发生改变):
可以发现必败态是若干条斜线,初始斜线是 x = y x=y x = y  ,特殊点会导致斜线向下和向右平移,发现这是个二维数点,扫描线维护使其向 x x x   轴方向平移的个数,树状数组维护 y y y   轴方向,用 x − y x-y x − y   的值判断是否在斜线上即可。代码 。
非公平组合 
比较有趣。
[AGC048D] Pocky Game 
Portal .
设 f l , r f_{l,r} f l , r    代表 a l a_l a l    至少为多少才能使得 [ l , r ] [l,r] [ l , r ]   先手必胜,g l , r g_{l,r} g l , r    代表 a r a_r a r    至少为多少才能使得 [ l , r ] [l,r] [ l , r ]   后手必胜。转移时由于最后是一个一个取,直接算即可,代码 。
[CF1033G] Chip Game 
Portal .
模 a + b a+b a + b   意义下的局面是等价的,考虑枚举 a + b a+b a + b  ,将 v v v   排序,计算出合法的值域 [ v i − 1 + 1 , v i ] [v_{i-1}+1,v_i] [ v i − 1  + 1 , v i  ]  ,而且应该减去存在两个 2 a ≤ v i 2a\le v_i 2 a ≤ v i    的情况,随便算算就好了。代码 。
题车