算法
欧几里得算法
证明
第一种方法是根据更相减损 :
gcd ( a , b ) = gcd ( a , a − b ) = gcd ( b , a − b ) \gcd(a,b) = \gcd(a,a-b) = \gcd(b,a-b) g cd( a , b ) = g cd( a , a − b ) = g cd( b , a − b )
更相减损的证明就是 d ∣ a , d ∣ b d \mid a,d \mid b d ∣ a , d ∣ b 则 d ∣ ( a − b ) d \mid (a-b) d ∣ ( a − b ) ,反之亦然,因此他们的公约数相同,最大公约数相同,得证。
然后根据更相减损每次给 a a a 减去 b b b 直到 a < b a < b a < b ,这个过程就等价于 a a a 对 b b b 取模。
然后欧几里得算法得证。
第二种方法是 :
不妨假设 a > b a > b a > b
容易发现 : 如果 b ∣ a b \mid a b ∣ a ,那么 b b b 就是两者的最大公约数。
对于不能整除时 : 我们可以设 a = k b + r a = kb + r a = k b + r ,其中 r < b r < b r < b 。
我们要证明的就是 gcd ( a , b ) = gcd ( b , a m o d b ) \gcd(a,b) = \gcd(b,a \bmod b \; ) g cd( a , b ) = g cd( b , a mod b ) 。过程如下 :
因为 a = k b + r a = kb + r a = k b + r ,所以显然有 r = a m o d b r = a \bmod b r = a mod b 。
设 d ∣ a , d ∣ b d \mid a,d\mid b d ∣ a , d ∣ b ,由 c = a − k b c = a - kb c = a − k b 同除 d d d
可得 : r d = a d − k b d \frac{r}{d} = \frac{a}{d} - k\frac{b}{d} d r = d a − k d b 。
等号右边显然是整数,因此 d ∣ r d \mid r d ∣ r ,所以任意 a , b a,b a , b 的公约数也是 a m o d b a \bmod b a mod b 的公约数。公约数相同,因此最大公约数也相同。
反过来证明的方法几乎一样 :
设 d ∣ r , d ∣ b d \mid r,d\mid b d ∣ r , d ∣ b ,由 c = a − k b c = a - kb c = a − k b 同除 d d d
同样可得 :
r d + k b d = a d \frac{r}{d} + k\frac{b}{d} = \frac{a}{d} d r + k d b = d a
式子左侧显然为整数,所以有 d ∣ a d \mid a d ∣ a ,所以充分性和必要性都得证,我们得出命题等价:
gcd ( a , b ) = gcd ( b , a m o d b ) \gcd(a,b) = \gcd(b,a \bmod b) g cd( a , b ) = g cd( b , a mod b )
于是由这个式子我们显然有了实现 :
实现
namespace way1{
int gcd(int m,int n)
{
int r;
if (m < n) std :: swap(m,n);
while(m % n)//辗转相除
{
r = m % n;
m = n;
n = r;
}
return n;
}
}
namespace way2{
int gcd(int x,int y)
{
return y ? gcd(y,x % y) : x;
}
}
namespace way3{
int gcd(int x, int y)
{
while(y ^= x ^= y ^= x %= y);
return x;
}
}
(当然可以直接 __gcd )
例题是UVA11426
那就推一下这个例题的式子罢 :
∑ i = 1 n ∑ j = i + 1 n = ∑ j = 2 n ∑ i = 1 j − 1 gcd ( i , j ) = ∑ d = 1 n d × ∑ j = 2 n ∑ i = 1 j − 1 [ gcd ( i , j ) = d ] = ∑ d = 1 n d × ∑ j = 2 ⌊ n d ⌋ ∑ i = 1 j − 1 [ i ⊥ j ] = ∑ d = 1 n d × ∑ j = 2 ⌊ n d ⌋ φ ( j ) \begin{split}
\sum_{i=1}^n \sum_{j = i+1}^n &= \sum_{j = 2}^n \sum_{i = 1}^{j-1} \gcd(i,j)\\
&= \sum_{d=1}^n d \times \sum_{j=2}^n \sum_{i = 1}^{j-1}[\gcd(i,j) = d] \\
&= \sum_{d=1}^n d \times \sum_{j=2}^{\lfloor \frac{n}{d} \rfloor} \sum_{i=1}^{j-1}[i \bot j]\\
&= \sum_{d=1}^n d \times \sum_{j=2}^{\lfloor \frac{n}{d} \rfloor}\varphi(j)\\
\end{split} i = 1 ∑ n j = i + 1 ∑ n = j = 2 ∑ n i = 1 ∑ j − 1 g cd( i , j ) = d = 1 ∑ n d × j = 2 ∑ n i = 1 ∑ j − 1 [ g cd( i , j ) = d ] = d = 1 ∑ n d × j = 2 ∑ ⌊ d n ⌋ i = 1 ∑ j − 1 [ i ⊥ j ] = d = 1 ∑ n d × j = 2 ∑ ⌊ d n ⌋ φ ( j )
到这里第一步已经成功了,都是经典操作也没什么难度。考虑进一步优化:
设 S ( x ) = ∑ j = 2 x φ ( j ) , f ( x ) = ∑ j = 1 x j S(x) = \sum_{j=2}^x \varphi(j) ,f(x) = \sum_{j = 1}^x j S ( x ) = ∑ j = 2 x φ ( j ) , f ( x ) = ∑ j = 1 x j .
显然原式变成 :
∑ d = 1 n d × S ( ⌊ n d ⌋ ) \sum_{d=1}^n d \times S({\lfloor \frac{n}{d} \rfloor}) d = 1 ∑ n d × S ( ⌊ d n ⌋ )
因为 ⌊ n d ⌋ \lfloor \frac{n}{d} \rfloor ⌊ d n ⌋ 被重复计算多次,显然考虑数论分块。
于是原式化为 :
∑ ( f ( r ) − f ( l − 1 ) ) × S ( ⌊ n l ⌋ ) \sum(f(r) - f(l-1)) \times S(\lfloor \frac{n}{l} \rfloor) ∑ ( f ( r ) − f ( l − 1 )) × S (⌊ l n ⌋)
预处理 f ( x ) , S ( x ) f(x),S(x) f ( x ) , S ( x ) 的值,最终对于 T T T 次询问总的时间复杂度是 O ( n + T n ) O(n + T \sqrt{n} ) O ( n + T n ) ,可以通过本题。
扩展欧几里得算法(exgcd)
推导
由裴蜀定理我们已知 : a x + b y = gcd ( a , b ) ax + by = \gcd(a,b) a x + b y = g cd( a , b ) 一定存在整数解。
使用 exgcd 可以得到上述方程的一组特解。
考虑解这个方程,显然当 b = 0 b = 0 b = 0 时我们有 : x = 1 , y ∈ Z x = 1,y \in Z x = 1 , y ∈ Z 。
当 b ≠ 0 b \neq 0 b = 0 时,我们设:
gcd ( a , b ) = a x 1 + b y 1 gcd ( b , a m o d b ) = b x 2 + ( a m o d b ) y 2 = b x 2 + ( a − ⌊ a b ⌋ b ) y 2 \begin{split}
&\gcd(a,b) = ax_1 + by_1\\
&\gcd(b,a \bmod b) = bx_2 + (a \bmod b)y_2 = bx_2 + (a - \lfloor \frac{a}{b} \rfloor b)y_2\\
\end{split} g cd( a , b ) = a x 1 + b y 1 g cd( b , a mod b ) = b x 2 + ( a mod b ) y 2 = b x 2 + ( a − ⌊ b a ⌋ b ) y 2
两式左边相等,那么拆开括号就有 :
a x 1 + b y 1 = a y 2 + b ( x 2 − ⌊ a b ⌋ y 2 ) ax_1 + by_1 = ay_2 + b(x_2 - \lfloor \frac{a}{b} \rfloor y_2) a x 1 + b y 1 = a y 2 + b ( x 2 − ⌊ b a ⌋ y 2 )
两边对应系数得 :
x 1 = y 2 , y 1 = x 2 − ⌊ a b ⌋ y 2 x_1 = y_2,y_1 = x_2 - \lfloor \frac{a}{b} \rfloor y_2 x 1 = y 2 , y 1 = x 2 − ⌊ b a ⌋ y 2
成功了!
于是我们就可以像求gcd一样递归求解了
代码实现
按照这个式子写的代码长这样 :
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x = 1;y = 0;
return a;
}
int d = exgcd(b,a % b,x,y);
int t = x;x = y;
y = t - a/b * y;
return d;
}
函数的返回值就是顺便求了一下gcd。
或者这样写 :
void exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x = 1;y = 0;
return;
}
exgcd(b,a%b,y,x);
y -= a/b*x;
}
本质上是完全等价的,而且这个板子更好记一些
之后令 g = gcd ( a , b ) g = \gcd(a,b) g = g cd( a , b )
则 lcm ( a , b ) = a ∗ b / g \text{lcm}(a,b) = a * b / g lcm ( a , b ) = a ∗ b / g
又 a x + lcm ( a , b ) + b y − lcm ( a , b ) = c ax + \text{lcm}(a,b) + by - \text{lcm}(a,b) = c a x + lcm ( a , b ) + b y − lcm ( a , b ) = c
所以就有 :
a ( x + b / g ) + b ( y − a / g ) = c a(x + b/g) + b(y - a/g) = c a ( x + b / g ) + b ( y − a / g ) = c
例题
一个很强的板子是 P5656 。
题意就是 :
T ( T ≤ 2 e 5 ) T(T \le 2e5) T ( T ≤ 2 e 5 ) 组数据,每组给出 a , b , c ∈ [ 1 , 10 9 ] a,b,c \in [1,10^9] a , b , c ∈ [ 1 , 1 0 9 ] ,询问使得 a x + b y = c ax+by = c a x + b y = c 成立的解。
若有正整数解,输出:
正整数解的个数
正整数解中最小的 x x x 和最大的 y y y
正整数解中最大的 x x x 和最小的 y y y
否则,若有整数解,输出 :
所有整数解中 x x x 的最小正整数值, y y y 的最小正整数值
否则,输出 − 1 -1 − 1
大概说一下这个题罢,虽然大概所有人都应该会写exgcd,但是能完整解决这道题的我觉得不多(
a x + b y = c ax + by = c a x + b y = c
显然,gcd ( a , b ) ∣ ( a x + b y ) \gcd(a,b) \mid (ax+by) g cd( a , b ) ∣ ( a x + b y )
故 gcd ( a , b ) ∤ c \gcd(a,b) \nmid c g cd( a , b ) ∤ c 时无解
然后我们就可以由exgcd求出一组整数 x 0 , y 0 x_0,y_0 x 0 , y 0 ,使得:
a x 0 + b y 0 = gcd ( a , b ) ax_0 + by_0 = \gcd(a,b) a x 0 + b y 0 = g cd( a , b )
等号两边同除 g c d ( a , b ) gcd(a,b) g c d ( a , b ) 后同乘 c c c ,就是 :
a x 0 c gcd ( a , b ) + b y 0 c gcd ( a , b ) = c a \frac{x_0c}{\gcd(a,b)}+ b \frac{y_0c}{\gcd(a,b)} = c a g cd( a , b ) x 0 c + b g cd( a , b ) y 0 c = c
于是我们找到了原方程的一组整数特解 x 1 , y 1 x_1,y_1 x 1 , y 1 :
x 1 = x 0 c gcd ( a , b ) , y 1 = y 0 c gcd ( a , b ) x_1 = \frac{x_0c}{\gcd(a,b)},y_1 = \frac{y_0c}{\gcd(a,b)} x 1 = g cd( a , b ) x 0 c , y 1 = g cd( a , b ) y 0 c
接下来考虑构造通解 :
对于 ∀ d ∈ Q \forall d \in Q ∀ d ∈ Q ,必然有 :
a ( x 1 + d b ) + b ( y 1 − d a ) = c a(x_1 + db) + b(y_1 - da) = c a ( x 1 + d b ) + b ( y 1 − d a ) = c
所以对于整数通解只需要保证 d a , d b ∈ Z da,db \in Z d a , d b ∈ Z 。
设 d d d 取到最小的可能的正值(实数)时 d x = d b , d y = d a d_x = db,d_y = da d x = d b , d y = d a 那么任意解中这两个变量与 x 1 , y 1 x_1,y_1 x 1 , y 1 的偏差一定分别是 d x d_x d x 与 d y d_y d y 的倍数。
那么显然最小时 d x = b gcd ( a , b ) , d y = a gcd ( a , b ) d_x = \frac{b}{\gcd(a,b)} , d_y = \frac{a}{\gcd(a,b)} d x = g c d ( a , b ) b , d y = g c d ( a , b ) a ,在 d = 1 gcd ( a , b ) d = \frac{1}{\gcd(a,b)} d = g c d ( a , b ) 1 时取到。
所以通解就是 :
x = x 1 + s d x , y = y 1 − s d y x = x_1 + sd_x,y = y_1 - sd_y x = x 1 + s d x , y = y 1 − s d y
其中 s ∈ Z s \in Z s ∈ Z
而且 x x x 与 y y y 取值的变化呈负相关。
显然而重要的 : s s s 越大, x x x 越大, y y y 越小,反之亦然。
考虑是否有正整数解的判定 :
限制 x > 0 x > 0 x > 0 ,则 x 1 + s d x > 0 , s > − x 1 d x x_1 + sd_x > 0 ,s > -\frac{x_1}{d_x} x 1 + s d x > 0 , s > − d x x 1
限制 y > 0 y > 0 y > 0 ,则 y 1 − s d y > 0 , s < y 1 d y y_1 - sd_y > 0 ,s < \frac{y_1}{d_y} y 1 − s d y > 0 , s < d y y 1
所以若要有正整数解,则要满足 :
− x 1 d x < s < y 1 d y -\frac{x_1}{d_x} < s < \frac{y_1}{d_y} − d x x 1 < s < d y y 1
当这个不等式无解时即无正整数解, s s s 位于左端点时即为 x x x 的最小正整数值, s s s 位于右端点时即为 y y y 的最小正整数值。
有解时即为有正整数解,正整数解个数就是在这个范围内的 s s s 的个数,容易求得。
x x x 的最大值和 y y y 的最小值都是在 s s s 的右端点取到,x x x 的最小值和 y y y 的最大值都是在 s s s 的左端点取到。
然后这道题就做完了。
代码的话就长这样 :
#include<bits/stdc++.h>
namespace Pozhu{
using namespace std;
typedef long long ll;
ll a,b,c;
ll exgcd(ll a,ll b,ll &x,ll &y);
void main()
{
cin >> a >> b >> c;
ll g = __gcd(a,b);
if(c % g)
{
cout << -1 << '\n';
return;
}
ll x,y;
exgcd(a,b,x,y);
x *= c / g,y *= c / g; //x1,y1
ll dx = b / g,dy = a / g; // x = x1 + sdx,y = y1 - sdy;
ll low_s = ceil((-x + 1) * 1.0 / dx);
ll high_s = floor((y - 1) * 1.0 / dy);
if(high_s >= low_s)
{
ll num = high_s - low_s + 1;
ll max_x = x + high_s * dx;
ll min_y = y - high_s * dy;
ll min_x = x + low_s * dx;
ll max_y = y - low_s * dy;
cout << num << ' ' << min_x << ' ' << min_y << ' ' << max_x << ' ' << max_y << '\n';
}
else
{
ll min_x = x + low_s * dx;
ll min_y = y - high_s * dy;
cout << min_x << ' ' << min_y << '\n';
}
return;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x = 1,y = 0;
return a;
}
ll g = exgcd(b,a%b,y,x);
y -= a / b * x;
return g;
}
}
signed main()
{
int T;
std :: ios :: sync_with_stdio(false);
for(std :: cin >> T;T;T--)
Pozhu :: main();
return 0;
}
类欧几里得算法
欧几里得全家桶(bushi
类欧几里得算法用来解决一些计数问题,尤其是可以出现下取整符号的情况。虽然考的比较少但是很好写~~,有时候可以拿来爆标~~。
推式子的过程有些复杂,写过专门的一篇文章,就放一个link 罢。
整除分块
也叫数论分块
放一些简单的东西来缓和一下气氛(
通常来讲我们会在以下场合使用整除分块 :
∑ i = 1 n ⌊ n i ⌋ \sum_{i = 1}^n\left \lfloor \frac{n}{i} \right \rfloor i = 1 ∑ n ⌊ i n ⌋
推导
大眼观察可以猜出 ⌊ n i ⌋ \left \lfloor \frac{n}{i} \right \rfloor ⌊ i n ⌋ 总是隔一段才变一次(因为是整除)
于是可以考虑以这个变化的位置为分界点进行一个分块,对于每一块我们只进行一次求值,然后乘上块长就可以得到一整块的答案。
假设我们当前的左端点是 l l l ,右端点是 r r r ,这个区间内单点的值为 k k k ,那么就有 :
k = ⌊ n l ⌋ = ⌊ n r ⌋ k = \left \lfloor \frac{n}{l} \right \rfloor = \left \lfloor \frac{n}{r} \right \rfloor k = ⌊ l n ⌋ = ⌊ r n ⌋
对于 i ∈ [ l , r ] i \in [l,r] i ∈ [ l , r ] ,显然 r r r 是所有 i i i 中的最大取值。因为 i ∗ k ≤ n , i ≤ n k i \ast k \le n, i \le \frac{n}{k} i ∗ k ≤ n , i ≤ k n 所以有 :
r = ⌊ n k ⌋ = ⌊ n ⌊ n l ⌋ ⌋ r = \left \lfloor \frac{n}{k} \right \rfloor = \left \lfloor \frac{n}{\left \lfloor \frac{n}{l} \right \rfloor} \right \rfloor r = ⌊ k n ⌋ = ⌊ ⌊ l n ⌋ n ⌋
其复杂度是 O ( n ) O(\sqrt{n}) O ( n ) ,证明会在下面给出
代码实现
for(int l = 1,r;l <= n;l = r + 1)
{
r = n / (n / l);
ans = ans + (r - l + 1) * (n / l);
}
要注意到整除分块的适用范围很广,以上模板仅是对于最平凡的场合,而整除分块常见于杜教筛和莫反当中,在相应文章中可以看到整除分块的频繁出现。
复杂度证明
这里给出整除分块的复杂度证明。
对于 :
∑ i = 1 n ⌊ n i ⌋ \sum_{i = 1}^n\left \lfloor \frac{n}{i} \right \rfloor i = 1 ∑ n ⌊ i n ⌋
我们把 i i i 的取值范围分为两部分进行讨论。
第一部分 : 1 ≤ i ≤ n 1 \le i \le \sqrt{n} 1 ≤ i ≤ n ,容易发现这样的 i i i 最多只有 n \sqrt{n} n 个,考虑最坏情况,每个 ⌊ n i ⌋ \left \lfloor \frac{n}{i} \right \rfloor ⌊ i n ⌋ 的取值都不同,此时块长为 1 1 1 ,最多有 n \sqrt{n} n 块。
第二部分 : n < i ≤ n \sqrt{n} < i \le n n < i ≤ n ,容易得到 ⌊ n i ⌋ < n \left \lfloor \frac{n}{i} \right \rfloor < \sqrt{n} ⌊ i n ⌋ < n ,这样的取值最多有 ( n − 1 ) (\sqrt{n} - 1) ( n − 1 ) 个,意味着最多有 ( n − 1 ) (\sqrt{n}-1) ( n − 1 ) 块。
于是块数最多为 2 n − 1 2 \sqrt{n} - 1 2 n − 1 ,我们对于每块内求解的复杂度为 O ( 1 ) O(1) O ( 1 ) ,于是总复杂度为 O ( n ) O(\sqrt{n}) O ( n ) ,得证。
例题
首先是模板题:H(n)
如果有一道题目是专门考察整除分块的,那么你一定很难看出来这是整除分块(
P2261 [CQOI2007]余数求和
给定 n , k n,k n , k ,n , k ≤ 10 9 n,k \le 10^9 n , k ≤ 1 0 9 ,求 :
∑ i = 1 n k m o d i \sum_{i = 1}^n k \bmod i i = 1 ∑ n k mod i
考虑模的意义是整除取余,于是有 :
a n s = ∑ i = 1 n ( k − i ⌊ k i ⌋ ) ans = \sum_{i = 1}^n (k - i \lfloor \frac{k}{i} \rfloor) an s = i = 1 ∑ n ( k − i ⌊ i k ⌋)
于是做完了,剩下的应该不用说了。
P3935 Calculating
进行一个没有难度的转化题意,发现是求 l ∼ r l \sim r l ∼ r 的因数个数之和。复杂度要求至多为根号级别。
考虑一个经典套路,于是我们把题意简化为求 1 ∼ n 1 \sim n 1 ∼ n 的因数个数之和。
那么考虑计算每一个数的贡献再合并,于是变成了枚举每个因数,统计它的倍数个数再求和。
关于这为什么就是答案,一个简单明了的解释是一个推导过程 :
f ( x ) = ∑ i = 1 x [ i ∣ x ] \begin{split}
f(x) &= \sum_{i = 1}^x[i \mid x]\\
\end{split} f ( x ) = i = 1 ∑ x [ i ∣ x ]
于是答案就是 :
∑ x = 1 n ∑ i = 1 x [ i ∣ x ] = ∑ i = 1 n ⌊ n i ⌋ \sum_{x = 1} ^ n \sum_{i = 1}^x[i \mid x] = \sum_{i = 1} ^ n \lfloor \frac{n}{i} \rfloor x = 1 ∑ n i = 1 ∑ x [ i ∣ x ] = i = 1 ∑ n ⌊ i n ⌋
最后一步转化是考虑 i i i 对于每一个倍数都产生 1 1 1 的贡献,于是 i i i 的贡献就是其倍数个数。
然后上一个整除分块,这题做完了。
Cipolla 算法
用来解决形如
x 2 ≡ n m o d p x^2 \equiv n \mod p x 2 ≡ n mod p
的问题(模意义开根)。其中 p p p 为奇素数。
这部分参考Kewth 的博客 ,具体而言,文章架构和讲述顺序大体一致。
那是一篇优秀的博客,我从那里学会了二次剩余。他大概比我讲的清楚些
解的数量
数学直觉告诉我们解可能不唯一,注意我们讨论的范围是 [ 0 , p ) [0,p) [ 0 , p ) 。
考虑两个不同解 x 1 , x 2 x_1,x_2 x 1 , x 2 ,代入原式易得 x 1 2 ≡ x 2 2 x_1^2 \equiv x_2^2 x 1 2 ≡ x 2 2 ,于是移项使用平方差公式,有 :( x 1 + x 2 ) ( x 1 − x 2 ) ≡ 0 (x_1 + x_2)(x_1 - x_2) \equiv 0 ( x 1 + x 2 ) ( x 1 − x 2 ) ≡ 0 。
由于他们是不同解,有 x 1 + x 2 ≡ 0 x_1 + x_2 \equiv 0 x 1 + x 2 ≡ 0 ,于是这两数为模意义下相反数,发现只有两个解。考虑是否有特殊情况,发现当一个解为 0 0 0 时只有一解。而剩余情况下,因为模数是奇素数,两数奇偶性不同,两数不可能相同。
这里涉及到一个二次剩余的概念,注意二次剩余是一种数,这个意义建立在一个模数下。对于一个模数 p p p ,一个非 0 0 0 整数 n n n ,如果 x 2 ≡ n m o d p x^2 \equiv n \mod p x 2 ≡ n mod p 存在整数解,那么 n n n 是一个二次剩余,否则不是。
同时可以发现每一对相反数都对应一个二次剩余,且这些二次剩余两两不同(若相同则有四个解显然不成立)。于是二次剩余的数量是 p − 1 2 \frac{p-1}{2} 2 p − 1 ,剩下的数都是非二次剩余,数量相同。
欧拉准则
用来判定一个数是否为二次剩余。
不妨认为 n n n 的范围是 [ 0 , p ) [0,p) [ 0 , p ) 。
特殊判定 n = 0 n=0 n = 0 的情况,它不是二次剩余,它模意义下的根只有一个,是它本身。
判定要用的内容是 :
如果 n n n 是二次剩余,当且仅当 n ( p − 1 2 ) ≡ 1 n^{(\frac{p-1}{2})} \equiv 1 n ( 2 p − 1 ) ≡ 1 ,否则 n n n 是非二次剩余,且n ( p − 1 2 ) ≡ − 1 n^{(\frac{p-1}{2})} \equiv -1 n ( 2 p − 1 ) ≡ − 1 。
下面是一个证明 :
若 n ( p − 1 2 ) ≡ 1 n ^ {(\frac{p-1}{2})} \equiv 1 n ( 2 p − 1 ) ≡ 1 ,那么将 n n n 表示为 g k g^k g k ,其中 g g g 是模 p p p 意义下的原根。
那么 g k p − 1 2 ≡ 1 g^{k \frac{p-1}{2}} \equiv 1 g k 2 p − 1 ≡ 1 。由于 g g g 是原根,有 p − 1 ∣ k p − 1 2 p-1 \mid k \frac{p-1}{2} p − 1 ∣ k 2 p − 1 ,这是阶的性质,可见阶与原根 中对于阶性质的介绍。
于是 k k k 一定是偶数,那么 x = g k 2 x = g^{\frac{k}{2}} x = g 2 k 即为所求解。
我们通过构造可行解的方法证明了此时的 n n n 是二次剩余。
由费马小定理得到 n p − 1 ≡ 1 n^{p-1} \equiv 1 n p − 1 ≡ 1 ,由于 p p p 是奇素数,p − 1 p-1 p − 1 一定是偶数,于是化为 n 2 ( p − 1 2 ) ≡ 1 n^{2(\frac{p-1}{2})} \equiv 1 n 2 ( 2 p − 1 ) ≡ 1 。那么 n ( p − 1 2 ) n^{(\frac{p-1}{2})} n ( 2 p − 1 ) 是 1 1 1 开根的解,于是 n ( p − 1 2 ) n^{(\frac{p-1}{2})} n ( 2 p − 1 ) 的值只能是 1 1 1 或 − 1 -1 − 1 。
如果 n n n 是二次剩余,那么 x 2 ≡ n x^2 \equiv n x 2 ≡ n 有整数解,那么就有 x p − 1 ≡ 1 x^{p-1} \equiv 1 x p − 1 ≡ 1 。
于是我们证明了对于任意一个二次剩余 n n n 都有上式成立。
于是我们证明了充分性和必要性,得到 n n n 是二次剩余等价于 n ( p − 1 2 ) ≡ 1 n^{(\frac{p-1}{2})} \equiv 1 n ( 2 p − 1 ) ≡ 1 。
实际上有个东西叫勒让德符号,但是与上面的判定方法本质相同,现在的介绍足以解决这一问题,就不再引入新的概念。
那么有了这个引理之后,我们应该如何求解原问题呢?
Cipolla
找到一个 a a a 满足 a 2 − n a^2 - n a 2 − n 是非二次剩余。非二次剩余的数量大致占一半,于是期望两次可以找到一个合法的 a a a ,这是一个小常数。
然后定义 i 2 ≡ a 2 − n i^2 \equiv a^2 -n i 2 ≡ a 2 − n ,这并不是二次剩余,于是像是对负数开根那样,我们的 i i i 是一个“虚数”,于是可以把所有数表示成 a + b i a + bi a + bi 的形式,其中 a , b ∈ [ 0 , p ) a,b \in [0,p) a , b ∈ [ 0 , p ) 。
结论是 ( a + i ) p + 1 ≡ n (a+i) ^ {p + 1} \equiv n ( a + i ) p + 1 ≡ n 。
证明 :
引理1
i p ≡ − i i^p \equiv -i i p ≡ − i
证明 :
i p ≡ i ( i 2 ) p − 1 2 ≡ i ( a 2 − n ) p − 1 2 ≡ − i i^p \equiv i (i^2) ^ {\frac{p-1}{2}} \equiv i (a^2 - n) ^ {\frac{p-1}{2}} \equiv -i i p ≡ i ( i 2 ) 2 p − 1 ≡ i ( a 2 − n ) 2 p − 1 ≡ − i
得证。
引理2
( A + B ) p ≡ A p + B p (A + B) ^ p \equiv A^p + B^p ( A + B ) p ≡ A p + B p
证明类似 Lucas 定理的证明中对于引理二 的证明,用二项式定理展开即可,不再赘述。
有了这两个引理之后我们可以考虑去证明上述结论 :
( a + i ) p + 1 ≡ ( a p + i p ) ( a + i ) ≡ ( a − i ) ( a + i ) ≡ a 2 − i 2 ≡ n (a+i) ^ {p+1} \equiv (a^p + i^p)(a + i) \equiv (a-i)(a+i) \equiv a^2 - i^2 \equiv n ( a + i ) p + 1 ≡ ( a p + i p ) ( a + i ) ≡ ( a − i ) ( a + i ) ≡ a 2 − i 2 ≡ n
于是得证。
于是 ( a + i ) p + 1 2 (a+i) ^ {\frac{p+1}{2}} ( a + i ) 2 p + 1 就是一个解,其相反数是另一个解。
但是这是虚数运算,大家当然会产生疑问 : 这个结果的虚部一定为 0 0 0 吗?
答案是肯定的。用反证法可以得到这个结论:
假设有 ( A + B i ) 2 ≡ n (A + Bi) ^ 2 \equiv n ( A + B i ) 2 ≡ n 且 B ≠ 0 B \neq 0 B = 0 。
注意为什么我们设这样的形式,原因当然是方便讨论。注意上边的解一定可以找到一个这种形式的叙述表示。
于是 A 2 + B 2 i 2 + 2 A B i ≡ n A^2 + B^2i^2 + 2 ABi \equiv n A 2 + B 2 i 2 + 2 A B i ≡ n ,移项得到 A 2 + B 2 ( a 2 − n ) − n ≡ − 2 A B i A^2 + B^2(a^2 - n) - n \equiv -2ABi A 2 + B 2 ( a 2 − n ) − n ≡ − 2 A B i
这里可以运用等式的基本性质,等号左边没有虚部,那么右边的虚部也一定为 0 0 0 。
即 A B = 0 AB = 0 A B = 0 ,已知 B ≠ 0 B \neq 0 B = 0 ,那么 A = 0 A = 0 A = 0
于是化简式子 :
B 2 ( a 2 − n ) ≡ n B^2(a^2 - n) \equiv n B 2 ( a 2 − n ) ≡ n
也就是 :
i 2 ≡ n B − 2 i^2 \equiv n B^{-2} i 2 ≡ n B − 2
B − 2 B^{-2} B − 2 是一个二次剩余,因为显然有一解为 B − 1 B^{-1} B − 1 。
n n n 也是二次剩余,那么 n B − 2 nB^{-2} n B − 2 显然也是二次剩余,解是原解的乘积。
这与 i 2 i^2 i 2 是非二次剩余矛盾,就像是虚数的 i 2 > 0 i^2 > 0 i 2 > 0 一样离谱。
于是我们得到了矛盾,证明了假设不成立,即不存在那样的 B B B ,我们求出的解虚部一定为 0 0 0 。
那么我们就可以解决开头提出的问题了。
这是板子题 : P5491 【模板】二次剩余 。
BSGS算法
BSGS(baby-step giant-step) ,即大步小步算法,常用于求解离散对数问题。也就是说,该算法可以在 O ( p ) O(\sqrt{p}) O ( p ) 的时间内求解
a x ≡ b ( m o d p ) a^x \equiv b \; (\bmod p \; ) a x ≡ b ( mod p )
普通的BSGS算法要求 a ⊥ p a \bot p a ⊥ p ,不要求 p p p 是素数。
令 x = A ⌈ p ⌉ − B x = A \lceil \sqrt{p} \rceil - B x = A ⌈ p ⌉ − B ,其中 0 ≤ A , B ≤ ⌈ p ⌉ 0 \le A,B \le \lceil \sqrt{p} \rceil 0 ≤ A , B ≤ ⌈ p ⌉ ,则有 a A ⌈ p ⌉ − B ≡ b ( m o d p ) a^{A \lceil \sqrt{p} \rceil - B} \equiv b \; (\bmod p \;) a A ⌈ p ⌉ − B ≡ b ( mod p ) ,两边同乘 a B a^B a B ,那么我们得到 :
a A ⌈ p ⌉ ≡ b ⋅ a B ( m o d p ) a^{A \lceil \sqrt{p} \rceil} \equiv b \cdot a^B \; (\bmod p \; ) a A ⌈ p ⌉ ≡ b ⋅ a B ( mod p )
因为我们已知 a , b a,b a , b ,于是我们可以枚举 B B B ,预处理出所有 b a B ba^B b a B 的取值,使用 map 或 hash 建立起相应的映射,然后逐一计算 a A ⌈ p ⌉ a^{A \lceil \sqrt{p} \rceil} a A ⌈ p ⌉ ,也就是枚举 A A A ,检查是否有与之对应的 b a B ba^B b a B ,从而我们可以得到所有的 x x x ,x = A ⌈ p ⌉ − B x = A \lceil \sqrt{p} \rceil - B x = A ⌈ p ⌉ − B
显然由 A , B ≤ p A,B \le \sqrt{p} A , B ≤ p ,上述算法的时间复杂度为 Θ ( p ) \Theta(\sqrt{p}) Θ ( p ) ,若使用 map 则多一个 log \log log 。
要求 a ⊥ p a \bot p a ⊥ p 的原因 :
我们求得的是 A , B A,B A , B ,而要通过 A , B A,B A , B 的值推出 x x x 的值需要 a A ⌈ p ⌉ ≡ b a B ⇔ a A ⌈ p ⌉ − B ≡ b ( m o d p ) a^{A\lceil \sqrt{p} \rceil } \equiv ba^B \Leftrightarrow a^{A\lceil \sqrt{p} \rceil-B} \equiv b \; (\bmod p \;) a A ⌈ p ⌉ ≡ b a B ⇔ a A ⌈ p ⌉ − B ≡ b ( mod p ) ,即这个同余式对于两边同除 a B a^B a B 仍成立。
所以必须要有 a B ⊥ p a^B \bot p a B ⊥ p ,也就是 a ⊥ p a \bot p a ⊥ p 。
模板题是P3846 ,代码如下 :
#include<bits/stdc++.h>
namespace Pozhu{
using namespace std;
typedef long long ll;
ll a,x,n,p;
ll ksm(ll ,ll );
ll BSGS(ll ,ll ,ll );
void main()
{
scanf("%lld%lld%lld",&p,&a,&n);
ll ans = BSGS(a,n,p);
if(ans == -1)
puts("no solution");
else
printf("%lld",ans);
return;
}
ll BSGS(ll a,ll b,ll p)
{
b %= p;
map<ll ,ll > has;has.clear();
ll t = sqrt(p) + 1;
for(ll j = 0,tmp = b;j<t;tmp = tmp * a % p,j++)
has[tmp] = j;
a = ksm(a,t);
if(!a) return b == 0 ? 0 : -1;
for(ll i = 1,tmp = a;i<=t;tmp = tmp * a % p,i++)
if(has.count(tmp))
return i * t - has[tmp];
return -1;
}
ll ksm(ll a,ll b)
{
ll ans = 1;
for(;b;b>>=1,a = a * a % p) if(b & 1) ans = ans * a % p;
return ans;
}
}
signed main()
{
Pozhu :: main();
return 0;
}
BSGS算法给我们带来的教益不仅是解决了这个问题,还有其根号分治的思想。
灵活运用类似的思想,我们就可以解决这道题: Maximum Sine
提示:转化题意,考虑类似的分块思路。
放一个题解 ,使这题有头有尾。
扩展BSGS
扩展BSGS依然用来解决这个问题 :
a x ≡ b ( m o d p ) a^x \equiv b \;(\bmod p \;) a x ≡ b ( mod p )
但是其中 a , p a,p a , p 不一定互质。
当 a ⊥ p a \bot p a ⊥ p 时,在模 p p p 意义下 a a a 存在逆元,因此可以使用BSGS算法求解(同除 a B a^B a B 即同乘 a a a 的逆元的 B B B 次方,可行)。 于是我们想办法让他们变的互质。
我们设 d 1 = gcd ( a , p ) d_1 = \gcd(a,p) d 1 = g cd( a , p ) ,如果 d 1 ∤ b d_1 \nmid b d 1 ∤ b ,则原方程无解。否则我们把方程和模数同时除以 d 1 d_1 d 1 ,得到 :
a d 1 ⋅ a x − 1 ≡ b d 1 ( m o d p d 1 ) \frac{a}{d_1}\cdot a^{x-1} \equiv \frac{b}{d_1} \;(\bmod \frac{p}{d_1} \; ) d 1 a ⋅ a x − 1 ≡ d 1 b ( mod d 1 p )
如果此时 a a a 和 p d 1 \frac{p}{d_1} d 1 p 仍不互质就再除,设 d 2 = gcd ( a , p d 1 ) d_2 = \gcd(a,\frac{p}{d_1}) d 2 = g cd( a , d 1 p ) 。如果 d 2 ∤ b d 1 d_2 \nmid \frac{b}{d_1} d 2 ∤ d 1 b ,则原方程无解,否则同时除以 d 2 d_2 d 2 得到 :
a 2 d 1 d 2 ⋅ a x − 2 ≡ b d 1 d 2 ( m o d p d 1 d 2 ) \frac{a^2}{d_1d_2}\cdot a^{x-2} \equiv \frac{b}{d_1d_2} \;(\bmod \frac{p}{d_1d_2} \; ) d 1 d 2 a 2 ⋅ a x − 2 ≡ d 1 d 2 b ( mod d 1 d 2 p )
不停地这样做下去,直到 a ⊥ p d 1 d 2 ⋯ d k a \bot \frac{p}{d_1d_2\cdots d_k} a ⊥ d 1 d 2 ⋯ d k p 。
记 D = ∏ i d i D = \prod_id_i D = ∏ i d i ,那么原方程就是 :
a k D ⋅ a x − k ≡ b D ( m o d p D ) \frac{a^k}{D} \cdot a^{x-k} \equiv \frac{b}{D} \; (\bmod \frac{p}{D} \; ) D a k ⋅ a x − k ≡ D b ( mod D p )
由 a ⊥ p D a \bot \frac{p}{D} a ⊥ D p 可得 a k D ⊥ p D \frac{a^k}{D} \bot \frac{p}{D} D a k ⊥ D p ,这样 a k D \frac{a^k}{D} D a k 就有逆元了,方程两边同乘它的逆元,问题就转化为一个普通的BSGS问题,解出 x − k x-k x − k 的值之后再加上 k k k 就是要求的解。
但是可能会出现 x ≤ k x \le k x ≤ k 的情况,我们可以在知道 k k k 之后直接进行 k k k 次枚举验证答案来避免这种情况对求解造成影响。
模板题是 P4195 ,代码很不优美就不放了。
BSGS解高次剩余
求解
x a ≡ b ( m o d p ) x^a \equiv b \;(\bmod p \; ) x a ≡ b ( mod p )
其中 p p p 为质数。
该模型可以通过一系列转化变为BSGS的基本形式。
前置知识是阶和原根。
由于式子中的 p p p 为质数,那么一定存在原根 g g g ,因此对于模 p p p 意义下任意的数 x ( 0 ≤ x ≤ p ) x(0 \le x \le p) x ( 0 ≤ x ≤ p ) 有且仅有一个数 i i i 满足 x = g i x = g^i x = g i
Pollard Rho 算法
Fermat 素性测试
Miller-Rabin 素性测试
定理
算数基本定理(唯一分解定理)
任意不是质数的正整数 a a a 能唯一分解为有限个质数幂的乘积 :
a = ∏ 1 ≤ i ≤ m p i c i a = \prod_{1 \le i \le m} p_i^{c_i} a = 1 ≤ i ≤ m ∏ p i c i
约数个数定理
“小学奥数”
内容
对于一个大于 1 1 1 的正整数 n n n 可以分解质因数 :
n = ∏ i = 1 k p i a i = p 1 a 1 ⋅ p 2 a 2 ⋯ p k a k n = \prod_{i = 1}^k p_i^{a_i} = p_1^{a_1} \cdot p_2^{a_2} \cdots p_k ^ {a_k} n = i = 1 ∏ k p i a i = p 1 a 1 ⋅ p 2 a 2 ⋯ p k a k
则 n n n 的正约数个数就是 :
τ ( n ) = ∏ i = 1 k ( a i + 1 ) = ( a 1 + 1 ) ( a 2 + 1 ) ⋯ ( a k + 1 ) \tau(n) = \prod_{i = 1}^k (a_i + 1) = (a_1 + 1)(a_2 + 1) \cdots (a_k + 1) τ ( n ) = i = 1 ∏ k ( a i + 1 ) = ( a 1 + 1 ) ( a 2 + 1 ) ⋯ ( a k + 1 )
证明
对于上述唯一分解的结果观察 :
p 1 a 1 p_1^{a_1} p 1 a 1 的约数有 : p 1 0 , p 1 1 ⋯ p 1 a 1 p_1^0,p_1^1 \cdots p_1^{a_1} p 1 0 , p 1 1 ⋯ p 1 a 1 共 ( a 1 + 1 ) (a_1 + 1) ( a 1 + 1 ) 个,其他质因子同理。
于是总的因子个数可以由乘法原理得到 :
τ ( n ) = ∏ i = 1 k ( a i + 1 ) = ( a 1 + 1 ) ( a 2 + 1 ) ⋯ ( a k + 1 ) \tau(n) = \prod_{i = 1}^k (a_i + 1) = (a_1 + 1)(a_2 + 1) \cdots (a_k + 1) τ ( n ) = i = 1 ∏ k ( a i + 1 ) = ( a 1 + 1 ) ( a 2 + 1 ) ⋯ ( a k + 1 )
得证。
例题可以是 欧拉计划 T12 ,答案易求,这里不放了。
裴蜀定理
(又称贝祖定理)
对于任意不全为零的整数 a , b a,b a , b 都 ∃ x , y ∈ Z \exists x,y \in Z ∃ x , y ∈ Z ,使得 a x + b y = gcd ( a , b ) ax+by = \gcd(a,b) a x + b y = g cd( a , b ) 。
对于不定方程 a x + b y = m ax + by = m a x + b y = m ,其有解的充要条件是 gcd ( a , b ) ∣ m \gcd(a,b) \mid m g cd( a , b ) ∣ m
证明
充分性
即证明 : gcd ( a , b ) ∣ m \gcd(a,b) \mid m g cd( a , b ) ∣ m ,则 a x + b y = m ax+by=m a x + b y = m 有整数解
假设我们已知 a x + b y = gcd ( a , b ) ax+by = \gcd(a,b) a x + b y = g cd( a , b ) 有一组整数解 x 0 , y 0 x_0,y_0 x 0 , y 0 那么显然 a x + b y = m ax+by = m a x + b y = m 存在一组整数解 x 1 = x 0 m gcd ( a , b ) , y 1 = y 0 m gcd ( a , b ) x_1 = x_0 \frac{m}{\gcd(a,b)} ,y_1 = y_0 \frac{m}{\gcd(a,b)} x 1 = x 0 g c d ( a , b ) m , y 1 = y 0 g c d ( a , b ) m ,于是只需证明 a x + b y = gcd ( a , b ) ax+by = \gcd(a,b) a x + b y = g cd( a , b ) 一定存在整数解。
然后就可以从网上随便找一篇证明贺一下了
因为大家写的都是一样的而且都没有出处,我也不知道这个证明最先是在哪给出来的qwq,但是有些人写出锅的地方我还是能浅修一下。
设 d = gcd ( a , b ) d = \gcd(a,b) d = g cd( a , b ) ,显然有 d ∣ a , d ∣ b , d ∣ a x + b y d \mid a,d \mid b,d \mid ax+by d ∣ a , d ∣ b , d ∣ a x + b y
设 s s s 是 a x + b y ax+by a x + b y 的最小正数值,设 q = ⌊ a s ⌋ q = \lfloor \frac {a}{s} \rfloor q = ⌊ s a ⌋
于是我们有 r = a m o d s = a − q s = a − q ( a x + b y ) = a ( 1 − q x ) + b ( − q y ) r = a \bmod s = a - qs = a - q(ax+by) = a(1-qx) + b(-qy) r = a mod s = a − q s = a − q ( a x + b y ) = a ( 1 − q x ) + b ( − q y )
所以 r r r 也是 a x + b y ax+by a x + b y 的一个取值,并且由取模的来源我们已知 0 ≤ r < s 0 \le r < s 0 ≤ r < s ,不难得到 r = 0 r = 0 r = 0 ,于是由此我们得到 s ∣ a s \mid a s ∣ a ,同理可得 s ∣ b s \mid b s ∣ b ,于是 s ∣ gcd ( a , b ) s \mid \gcd(a,b) s ∣ g cd( a , b ) ,即 s ∣ d s \mid d s ∣ d
又因为 d ∣ ∀ a x + b y d \mid \forall ax+by d ∣ ∀ a x + b y ,而 s s s 是 a x + b y ax+by a x + b y 的一个取值,所以 d ∣ s d \mid s d ∣ s
于是证得 s = d s = d s = d (这里已经直接证明了下边的推论三)
于是因为 s s s 是 a x + b y ax+by a x + b y 的一个取值,d d d 是 a x + b y ax+by a x + b y 的一个取值。
换言之 a x + b y = gcd ( a , b ) ax+by = \gcd(a,b) a x + b y = g cd( a , b ) 一定存在整数解。
于是我们证明了这一结论。
必要性
即证明 : a x + b y = m ax + by = m a x + b y = m 有解,必定有 g c d ( a , b ) ∣ m gcd(a,b) \mid m g c d ( a , b ) ∣ m
(比较显然)
gcd ( a , b ) ∣ a \gcd(a,b) \mid a g cd( a , b ) ∣ a
gcd ( a , b ) ∣ b \gcd(a,b) \mid b g cd( a , b ) ∣ b
所以 gcd ( a , b ) ∣ m = a x + b y \gcd(a,b) \mid m = ax+by g cd( a , b ) ∣ m = a x + b y
应用
zh_dou : 用来做题
可以用来证明奇奇怪怪的东西和推式子
信息上对于这东西常见的套路是枚举gcd
如: 给你T组数据,求 ∑ i = 1 n ∑ j = 1 m gcd ( i , j ) \sum_{i = 1}^n \sum_{j = 1}^m \gcd(i,j) ∑ i = 1 n ∑ j = 1 m g cd( i , j )
其中有一步是标准的枚举gcd(经典枚举gcd)
∑ i = 1 n ∑ j = 1 m gcd ( i , j ) = ∑ i = 1 n ∑ j = 1 m ∑ d ∣ i , j d [ gcd ( i d , j d ) = 1 ] \begin{split}
& \sum_{i = 1}^n \sum_{j = 1}^m \gcd(i,j)\\
= & \sum_{i = 1}^n \sum_{j = 1}^m \sum_{d \mid i,j} d [\gcd( \frac{i}{d} , \frac{j}{d}) = 1]
\end{split} = i = 1 ∑ n j = 1 ∑ m g cd( i , j ) i = 1 ∑ n j = 1 ∑ m d ∣ i , j ∑ d [ g cd( d i , d j ) = 1 ]
一些推论
一、a a a ,b b b 可以组成所有 gcd ( a , b ) \gcd(a,b) g cd( a , b ) 的倍数(其实是定理的直接结论,等式的基本性质)
二、 a ⊥ b ⟺ ∃ x , y ∈ Z , a x + b y = 1 a\bot b \Longleftrightarrow \exists x,y \in Z, ax+by=1 a ⊥ b ⟺ ∃ x , y ∈ Z , a x + b y = 1
三、 a x + b y ax+by a x + b y 的最小正整数取值为 gcd ( a , b ) \gcd(a,b) g cd( a , b )
四、 对于不定方程 x 1 y 1 + x 2 y 2 + ⋯ + x n y n = k , y i ∈ Z x_1y_1 + x_2y_2 + \cdots + x_ny_n = k,y_i \in Z x 1 y 1 + x 2 y 2 + ⋯ + x n y n = k , y i ∈ Z ,其有解的充要条件为 gcd ( x i ) ∣ k \gcd({x_i}) \mid k g cd( x i ) ∣ k
五、我们考察不定方程 a x + b y = n ax+by = n a x + b y = n ,其中 a ⊥ b a \bot b a ⊥ b
若这个方程有一组解使得 x ≥ 0 , y ≥ 0 x \ge 0,y \ge 0 x ≥ 0 , y ≥ 0 ,那么称 n n n 可以被 a , b a,b a , b 表示。
那么 :
对于互质的 a , b a,b a , b ,记 C = a b − a − b C = ab-a-b C = ab − a − b 。由 a a a 与 b b b 互质, C C C 必然为奇数。则有结论 :
对任意的整数 n n n ,n n n 与 C − n C-n C − n 中有且仅有一个可以被表示
(对称性)
所以对称性总结一下就是 :
可表示的数与不可表示的数在区间 [ 0 , C ] [0,C] [ 0 , C ] 对称(关于 C C C 的一半对称)。0 0 0 可被表示,C C C 不可被表示;负数不可被表示,大于 C C C 的数可被表示。
证明 :
由于 a ⊥ b a \bot b a ⊥ b ,原方程有整数解(gcd ( a , b ) = 1 , a x + b y = n × gcd ( a , b ) \gcd(a,b) = 1,ax + by = n \times \gcd(a,b) g cd( a , b ) = 1 , a x + b y = n × g cd( a , b ) ) 。
设一组特解为 x = x 0 , y = y 0 x= x_0,y = y_0 x = x 0 , y = y 0
则通解为:
{ x = x 0 + b t y = y 0 − a t \left\{\begin{matrix}
x = x_0 + bt \\
y = y_0 - at
\end{matrix}\right. { x = x 0 + b t y = y 0 − a t
其中 t ∈ Z t \in Z t ∈ Z 。不难发现我们可以通过调整 t t t 的取值使得 y ∈ [ 0 , a − 1 ] y \in [0,a-1] y ∈ [ 0 , a − 1 ] ,这只需要在 y 0 y_0 y 0 上加减若干个 a a a 。此时我们的 y y y 已经满足条件了。
第一步 : 首先我们证明大于 C C C 的数都可以被表示。当 n n n 大于 C C C 时:
a x = n − b y > a b − a − b − b y ≥ a b − a − b − b ( a − 1 ) = − a ax = n-by > ab-a-b-by \ge ab-a-b-b(a-1) = -a a x = n − b y > ab − a − b − b y ≥ ab − a − b − b ( a − 1 ) = − a
也就是说:
a x > − a , x > − 1 ax > -a,x > -1 a x > − a , x > − 1
因为 x x x 为整数,所以得到 x x x 为非负整数, n n n 可以被表示。
第二步 : 证明 C C C 不可被表示,进而 n n n 与 C − n C-n C − n 不可能都被表示。
考虑反证法。
设 C C C 可以被表示,也就是说 a x + b y = a b − a − b ax+by = ab-a-b a x + b y = ab − a − b 有非负整数解 x , y x,y x , y 。则 :
a b = a ( x + 1 ) + b ( y + 1 ) ab = a(x+1) + b(y+1) ab = a ( x + 1 ) + b ( y + 1 )
一个我并不喜欢的版本:
因为 a ⊥ b a \bot b a ⊥ b ,要使等式成立,显然有 :
a ≤ y + 1 , b ≤ x + 1 a \le y+1,b \le x+1 a ≤ y + 1 , b ≤ x + 1
(实际上大概连等号都挂不上罢)
而 a ⊥ b a \bot b a ⊥ b ,且等号右边可以合并同类项,所以我们有 :
a ∣ ( y + 1 ) , b ∣ ( x + 1 ) a \mid (y + 1),b \mid (x + 1) a ∣ ( y + 1 ) , b ∣ ( x + 1 )
显然上式化为 :
a b = a ( x + 1 ) + b ( y + 1 ) ≥ a b + a b = 2 a b ab = a(x + 1) + b(y + 1) \ge ab + ab = 2ab ab = a ( x + 1 ) + b ( y + 1 ) ≥ ab + ab = 2 ab
而 a b ab ab 显然不为0,矛盾。因此证得 C C C 不可能被表示。
(显然并不显然)
显然当 y y y 取值最小的时候对应的 x x x 取值最大
且由上述证明可知存在最小的 y ∈ [ 0 , a − 1 ] y \in [0,a-1] y ∈ [ 0 , a − 1 ]
那么下式取 y ∈ [ 0 , a − 1 ] y \in [0,a-1] y ∈ [ 0 , a − 1 ] ,可以得到最大的 x x x
a ( x + 1 ) = a b − b ( y + 1 ) = b ( a − y − 1 ) ≤ 0 a(x + 1) = ab - b(y + 1) = b(a - y - 1) \le 0 a ( x + 1 ) = ab − b ( y + 1 ) = b ( a − y − 1 ) ≤ 0
a > 0 a > 0 a > 0 则 x ≤ − 1 x \le -1 x ≤ − 1 ,不成立,则 C C C 不可以被表示,故得证。
因为 y y y 取最大值
此时若 n n n 与 C − n C-n C − n 都能被表示,则 n n n 也能被表示,矛盾。因此我们得到 n n n 与 C − n C - n C − n 不可能都被表示。
所以第二步完成了
第三步 : 证明如果 n n n 不可以被表示,则 C − n C-n C − n 一定能被表示 (即 n n n 和 C − n C-n C − n 一定有一个能被表示)
由上可知 : 若 n n n 不可能被表示,因为我们已经保证了有合法的 y y y ,那么此时一定有 x < 0 x < 0 x < 0 。所以:
C − n = a b − a − b − a x − b y = a ( − x − 1 ) + b ( a − 1 − y ) C - n = ab-a-b-ax-by = a(-x-1) + b(a-1-y) C − n = ab − a − b − a x − b y = a ( − x − 1 ) + b ( a − 1 − y )
所以 − X − 1 -X-1 − X − 1 和 a − 1 − y a-1-y a − 1 − y 均为非负,则 C − n C-n C − n 可以被表示。
所以我们证明了对称性
费马小定理
若 p p p 为素数, g c d ( a , p ) = 1 gcd(a,p) = 1 g c d ( a , p ) = 1 , 则 a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1 \space (\bmod p \;) a p − 1 ≡ 1 ( mod p ) 。
另一个等价的形式是 :
对于任意整数 a a a ,有 a p ≡ a ( m o d p ) a^p \equiv a \space (\bmod p \; ) a p ≡ a ( mod p ) 。
证明
设一个质数 p p p ,我们取一个不为 p p p 倍数的数 a a a 。
构造一个序列 : A = 1 , 2 , 3 , ⋯ , p − 1 A = {1,2,3,\cdots,p-1} A = 1 , 2 , 3 , ⋯ , p − 1 ,显然这个序列有这样一个性质 :
∏ i = 1 n A i ≡ ∏ i = 1 n ( A i × a ) ( m o d p ) \prod_{i=1}^nA_i \equiv \prod_{i = 1}^n (A_i \times a )\space ( \bmod p\; ) i = 1 ∏ n A i ≡ i = 1 ∏ n ( A i × a ) ( mod p )
对性质的证明 :
∵ ( A i , p ) = 1 \because (A_i,p) = 1 ∵ ( A i , p ) = 1
∴ ( A i × a , p ) = 1 \therefore (A_i \times a,p) = 1 ∴ ( A i × a , p ) = 1
又因为每个 ( A i × a ) ( m o d p ) (A_i \times a )\space ( \bmod p \;) ( A i × a ) ( mod p ) 都不同,且 ( A i × a ) ( m o d p ) < p (A_i \times a )\space ( \bmod p \;) < p ( A i × a ) ( mod p ) < p 于是每一个 A i × a A_i \times a A i × a 都对应了一个 A i A_i A i
所以 ( A i × a ) ( m o d p ) (A_i \times a )\space ( \bmod p \;) ( A i × a ) ( mod p ) 的取值取遍了 [ 1 , p − 1 ] [1,p-1] [ 1 , p − 1 ]
设 f = ( p − 1 ) ! f = (p-1)! f = ( p − 1 )! ,则 f ≡ a × A 1 × a × A 2 × ⋯ × a × A p − 1 ( m o d p ) f \equiv a \times A_1 \times a \times A_2 \times \cdots \times a \times A_{p-1} ( \bmod p \;) f ≡ a × A 1 × a × A 2 × ⋯ × a × A p − 1 ( mod p )
a p − 1 × f ≡ f ( m o d p ) a^{p-1} \times f \equiv f ( \bmod p \;) a p − 1 × f ≡ f ( mod p )
所以
a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1 ( \bmod p \;) a p − 1 ≡ 1 ( mod p )
故得证。我认为这个证明方法是最简单的一种。
另外的证明方法是由于 m m m 为质数,对于欧拉定理代入 φ ( m ) = m − 1 \varphi(m) = m-1 φ ( m ) = m − 1 即可得到费马小定理。
euler定理
译名 : 欧拉定理
内容
若 gcd ( a , m ) = 1 \gcd(a,m) = 1 g cd( a , m ) = 1 ,则 a φ ( m ) ≡ 1 ( m o d m ) a^{\varphi(m)} \equiv 1 (\bmod m) a φ ( m ) ≡ 1 ( mod m ) 。
证明
构造一个模 m m m 意义下的简化剩余系 r 1 , r 2 , … , r φ ( m ) r_1,r_2,\dots,r_{\varphi(m)} r 1 , r 2 , … , r φ ( m ) ,由于 a ⊥ m a \bot m a ⊥ m ,不难得到 a r 1 , a r 2 , … , a r φ ( m ) ar_1,ar_2,\dots,ar_{\varphi(m)} a r 1 , a r 2 , … , a r φ ( m ) 同样为模 m m m 意义下的简化剩余系。
于是有乘积相等(简系的元素相同): r 1 ⋅ r 2 ⋅ ⋯ ⋅ r φ ( m ) ≡ a r 1 ⋅ a r 2 ⋅ ⋯ ⋅ a r φ ( m ) ≡ a φ ( m ) ⋅ r 1 ⋅ r 2 ⋅ ⋯ ⋅ r φ ( m ) r_1 \cdot r_2 \cdot \dots \cdot r_{\varphi(m)} \equiv ar_1 \cdot ar_2 \cdot \dots \cdot ar_{\varphi(m)} \equiv a^{\varphi(m)} \cdot r_1 \cdot r_2 \cdot \dots \cdot r_{\varphi(m)} r 1 ⋅ r 2 ⋅ ⋯ ⋅ r φ ( m ) ≡ a r 1 ⋅ a r 2 ⋅ ⋯ ⋅ a r φ ( m ) ≡ a φ ( m ) ⋅ r 1 ⋅ r 2 ⋅ ⋯ ⋅ r φ ( m )
那么两边消去简系之积得到:
a φ ( m ) ≡ 1 ( m o d m ) a^{\varphi(m)} \equiv 1 (\bmod m) a φ ( m ) ≡ 1 ( mod m )
于是欧拉定理得证。
欧拉定理本身的应用较少,更多被应用的是扩展欧拉定理。
那么下面我们来介绍扩展欧拉定理的内容。
扩展euler定理
内容
a b ≡ { a b m o d φ ( m ) gcd ( a , m ) = 1 a b gcd ( a , m ) ≠ 1 , b < φ ( m ) a ( b m o d φ ( m ) ) + φ ( m ) gcd ( a , m ) ≠ 1 , b ≥ φ ( m ) ( m o d m ) a^b \equiv \begin{cases}
a^{b \bmod \varphi(m)} & \gcd(a,m) = 1\\
a^b & \gcd(a,m) \neq 1,b < \varphi(m)\\
a^{(b \bmod \varphi(m)) + \varphi(m)} & \gcd(a,m) \neq 1,b \ge \varphi(m)
\end{cases}
(\bmod m) a b ≡ ⎩ ⎨ ⎧ a b mod φ ( m ) a b a ( b mod φ ( m )) + φ ( m ) g cd( a , m ) = 1 g cd( a , m ) = 1 , b < φ ( m ) g cd( a , m ) = 1 , b ≥ φ ( m ) ( mod m )
第二行表示此时不能降幂,对于一般问题下的 m m m ,此时的范围已经足够小,我们可以接受直接求解的复杂度。
实际上扩展欧拉定理的形式优美,易于记忆,即使不了解证明,在很大程度上应用也不会受到限制。
倘若想要了解详细的证明过程,可以参考 oi-wiki 中的内容(尽管这里也是引用的证明)。
受到一些限制,这里暂不展开描述扩展欧拉定理的证明。
放一下模板题:P5091 【模板】扩展欧拉定理
然后可以尝试做一下这题:P4139 上帝与集合的正确用法
wilson定理及扩展
译名 : 威尔逊定理
内容
对于素数 p p p 有 :
( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)! \equiv -1 (\bmod p \;) ( p − 1 )! ≡ − 1 ( mod p )
证明
oi-wiki上的证明看起来很严谨,这里随便给出一个证明 :
2 ∼ p − 2 2 \sim p-2 2 ∼ p − 2 的数在模 p p p 意义下都有唯一逆元,且不是本身,于是它和逆元配对消掉,剩下的只有 1 1 1 和 p − 1 p-1 p − 1 ,1 1 1 没有贡献, p − 1 ≡ − 1 p-1 \equiv -1 p − 1 ≡ − 1 ,于是定理得证。
二项式定理
内容
二项式定理表明了二项式幂次展开后的各项系数:
( a + b ) n = ∑ i = 0 n ( n i ) a n − i b i (a+b)^n = \sum_{i = 0}^n \binom{n}{i}a^{n-i}b^i ( a + b ) n = i = 0 ∑ n ( i n ) a n − i b i
证明
当 n = 1 n = 1 n = 1 时,结论显然成立。
当结论对于 n − 1 n - 1 n − 1 成立时:
( a + b ) n = ( a + b ) n − 1 ∗ ( a + b ) = ( ∑ i = 0 n − 1 ( n − 1 i ) a n − i − 1 b i ) ( a + b ) = ∑ i = 0 n − 1 ( n − 1 i ) a n − i b i + ∑ i = 0 n − 1 ( n − 1 i ) a n − i − 1 b i + 1 = ∑ i = 0 n − 1 ( n − 1 i ) a n − i b i + ∑ i = 1 n ( n − 1 i − 1 ) a n − i b i = ( n − 1 0 ) a n b 0 + ∑ i = 1 n − 1 ( n i ) a n − i b i + ( n − 1 n − 1 ) a 0 b n \begin{split}
(a+b)^n &= (a+b)^{n-1} * (a+b)\\
&= \left ( \sum_{i = 0}^{n-1} \binom{n-1}{i} a^{n-i-1} b^i \right ) (a+b)\\
&= \sum_{i = 0}^{n-1} \binom{n-1}{i} a^{n-i} b^i + \sum_{i = 0}^{n-1} \binom{n-1}{i} a^{n-i-1} b^{i+1}\\
&= \sum_{i = 0}^{n-1} \binom{n-1}{i} a^{n-i} b^i + \sum_{i = 1}^{n} \binom{n-1}{i-1} a^{n-i} b^{i}\\
&= \binom{n-1}{0} a^nb^0 + \sum_{i = 1}^{n-1} \binom{n}{i} a^{n-i}b^i + \binom{n-1}{n-1}a^0 b^n
\end{split} ( a + b ) n = ( a + b ) n − 1 ∗ ( a + b ) = ( i = 0 ∑ n − 1 ( i n − 1 ) a n − i − 1 b i ) ( a + b ) = i = 0 ∑ n − 1 ( i n − 1 ) a n − i b i + i = 0 ∑ n − 1 ( i n − 1 ) a n − i − 1 b i + 1 = i = 0 ∑ n − 1 ( i n − 1 ) a n − i b i + i = 1 ∑ n ( i − 1 n − 1 ) a n − i b i = ( 0 n − 1 ) a n b 0 + i = 1 ∑ n − 1 ( i n ) a n − i b i + ( n − 1 n − 1 ) a 0 b n
其中用到了 ( n k ) + ( n k − 1 ) = ( n + 1 k ) \binom{n}{k} + \binom{n}{k-1} = \binom{n+1}{k} ( k n ) + ( k − 1 n ) = ( k n + 1 ) 的结论。
易得 :
( n − 1 0 ) a n b 0 = ( n 0 ) a n b 0 \binom{n-1}{0} a^nb^0 = \binom{n}{0}a^nb^0 ( 0 n − 1 ) a n b 0 = ( 0 n ) a n b 0
( n − 1 n − 1 ) a 0 b n = ( n n ) a 0 b n \binom{n-1}{n-1}a^0 b^n = \binom{n}{n}a^0b^n ( n − 1 n − 1 ) a 0 b n = ( n n ) a 0 b n
于是我们有:
( a + b ) n = ∑ i = 0 n ( n i ) a n − i b i (a+b)^n = \sum_{i = 0}^n \binom{n}{i} a^{n-i}b^i ( a + b ) n = i = 0 ∑ n ( i n ) a n − i b i
于是此时结论对 n n n 也成立。
由数学归纳法证得结论成立。
广义二项式定理
牛顿还将二项式定理推广到了幂为一般实数的情形。
内容
( x + y ) a = ∑ k = 0 + ∞ ( a k ) x a − k y k (x + y) ^ a = \sum_{k = 0}^{+\infty} \binom{a}{k}x^{a-k}y^k ( x + y ) a = k = 0 ∑ + ∞ ( k a ) x a − k y k
其中 a a a 可以取任意实数, ( a 0 ) = 1 \binom{a}{0} = 1 ( 0 a ) = 1 。
中国剩余定理
中国剩余定理又称孙子定理,英文简写为CRT。
主要作用是求解线性同余方程组(也叫模线性方程组)。
像这样 :
{ x ≡ a 1 ( m o d n 1 ) x ≡ a 2 ( m o d n 2 ) ⋮ x ≡ a k ( m o d n k ) \left\{\begin{matrix}
x \equiv a_1 \;( \bmod n_1 \;) \\
x \equiv a_2 \;( \bmod n_2 \;) \\
\vdots\\
x \equiv a_k \;( \bmod n_k \;) \\
\end{matrix}\right. ⎩ ⎨ ⎧ x ≡ a 1 ( mod n 1 ) x ≡ a 2 ( mod n 2 ) ⋮ x ≡ a k ( mod n k )
普通的CRT要求模数之间两两互质。
流程
计算所有模数的乘积 N N N
对于第 i i i 个方程 :a. 计算 m i = N n i m_i = \frac{N}{n_i} m i = n i N b. 计算 m i m_i m i 在模 n i n_i n i 意义下的逆元 m i − 1 m_i^{-1} m i − 1 c. 计算 c i = m i m i − 1 c_i = m_im_i^{-1} c i = m i m i − 1 对 N N N 取模
方程组模 N N N 意义下的唯一解为 : x = ∑ i = 1 k a i c i x = \sum_{i=1}^{k} a_ic_i x = ∑ i = 1 k a i c i
模板题是 P1495
代码如下 :
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,r[20] , a[20], N = 1,ans;
void exgcd(ll a, ll b, ll &x, ll & y){
if(!b){
x = 1;
y = 0;
return;
}
exgcd(b,a%b,x,y);
ll t = x;
x = y;
y = t- (a/b) * y;
}
int main()
{
cin>>n;
for(int i= 1;i<=n;i++)
scanf("%lld%lld",&r[i],&a[i]),N *= r[i];
for(int i = 1;i<=n;i++)
{
ll m = N / r[i],b,y;
exgcd(m,r[i],b,y);
if(b < 0) b += r[i];
ans = (ans + a[i] * m * b);
}
cout<<ans%N;
}
(注意代码中输入的第一个数是模数,第二个数是余数。)
证明
要证明CRT的正确性,我们只需要证明通过上述过程算出来的 x x x 满足每一个同余方程。
对于不相等的 i i i 和 j j j ,我们显然有 n i ∣ m j n_i \mid m_j n i ∣ m j ,即 m j ≡ 0 ( m o d n i ) m_j \equiv 0 \;(\bmod n_i \;) m j ≡ 0 ( mod n i ) 。
于是 : c j ≡ m j ≡ 0 ( m o d n i ) c_j \equiv m_j \equiv 0 \;(\bmod n_i \;) c j ≡ m j ≡ 0 ( mod n i ) 。
又有 : c i ≡ m i ⋅ ( m i − 1 mod n i ) ≡ 1 ( m o d n i ) c_i \equiv m_i \cdot (m_i^{-1} \; \text{mod} \; n_i) \equiv 1 \;(\bmod n_i \;) c i ≡ m i ⋅ ( m i − 1 mod n i ) ≡ 1 ( mod n i )
所以我们可以得到 :
x ≡ ∑ j = 1 k a j c j ( m o d n i ) ≡ a i c i ( m o d n i ) ≡ a i ⋅ m i ⋅ ( m i − 1 m o d n i ) ( m o d n i ) ≡ a i ( m o d n i ) \begin{aligned}
x & \equiv \sum_{j=1}^{k} a_{j} c_{j} & &\left(\bmod n_{i} \; \right) \\
& \equiv a_{i} c_{i} & &\left(\bmod n_{i} \; \right ) \\
& \equiv a_{i} \cdot m_{i} \cdot\left(m_{i}^{-1} \bmod n_{i} \; \right ) & &\left(\bmod n_{i} \; \right) \\
& \equiv a_{i} & &\left(\bmod n_{i} \; \right)
\end{aligned} x ≡ j = 1 ∑ k a j c j ≡ a i c i ≡ a i ⋅ m i ⋅ ( m i − 1 mod n i ) ≡ a i ( mod n i ) ( mod n i ) ( mod n i ) ( mod n i )
于是当 i i i 取遍 1 ∼ k 1 \sim k 1 ∼ k 时,我们求得的 x x x 都是对应方程的合法解,于是我们证明了这个算法的正确性。
我们对输入的 a i a_i a i 没有特殊限制,因此对于任何一组输入的 a i {a_i} a i 都对应一个解 x x x 。
若 x ≠ y x \neq y x = y ,则总存在一个 i i i 使得 x x x 和 y y y 在模 n i n_i n i 下不同余。
扩展中国剩余定理
扩展中国剩余定理的简写为 EXCRT ,用来处理 CRT 中模数不互质的情况。
推荐一手 阮行止的博客 ,写的很详细。
设两个方程分别为 :
x ≡ a 1 ( m o d m 1 ) x \equiv a_1 (\bmod m_1 \; ) x ≡ a 1 ( mod m 1 )
x ≡ a 2 ( m o d m 2 ) x \equiv a_2 (\bmod m_2 \; ) x ≡ a 2 ( mod m 2 )
我们把同余方程转化成不定方程 :
x = m 1 k 1 + a 1 = m 2 k 2 + a 2 k 1 , k 2 ∈ Z x = m_1k_1 + a1 = m_2k_2 + a_2 \;\; k_1,k_2 \in Z x = m 1 k 1 + a 1 = m 2 k 2 + a 2 k 1 , k 2 ∈ Z
于是有 :
m 1 k 1 − m 2 k 2 = a 2 − a 1 m_1k_1 - m_2k_2 = a_2 - a_1 m 1 k 1 − m 2 k 2 = a 2 − a 1
由裴蜀定理可得 : 当 a 2 − a 1 a_2 - a_1 a 2 − a 1 不能被 gcd ( m 1 , m 2 ) \gcd(m1,m2) g cd( m 1 , m 2 ) 整除时,方程无解。
其他情况下,我们可以使用 e x g c d exgcd e xg c d 求出一组可行解 ( k 1 , k 2 ) (k_1,k_2) ( k 1 , k 2 ) ,具体流程如下 :
设 d = gcd ( m 1 , m 2 ) d = \gcd(m_1,m_2) d = g cd( m 1 , m 2 ) , p 1 = m 1 d p_1 = \frac{m_1}{d} p 1 = d m 1 , p 2 = m 2 d p_2 = \frac{m_2}{d} p 2 = d m 2 ,于是上式等价于 :
k 1 p 1 − k 2 p 2 = a 2 − a 1 d k_1p_1 - k_2p_2 = \frac{a_2 - a_1}{d} k 1 p 1 − k 2 p 2 = d a 2 − a 1
等号右边是整数。
x 0 p 1 + y 0 p 2 = 1 x_0 p_1 + y_0 p_2 = 1 x 0 p 1 + y 0 p 2 = 1
假设我们求得了这个方程的一组解 ( x 0 , y 0 ) (x_0,y_0) ( x 0 , y 0 ) ,那么我们就显然求出了 k 1 , k 2 k_1,k_2 k 1 , k 2 :
k 1 = a 2 − a 1 d x 0 , k 2 = − a 2 − a 1 d y 0 k_1 = \frac{a_2 - a_1}{d}x_0,k_2 = - \frac{a_2 - a_1}{d}y_0 k 1 = d a 2 − a 1 x 0 , k 2 = − d a 2 − a 1 y 0
于是 :
x = a 1 + k 1 m 1 = a 1 + a 2 − a 1 d x 0 m 1 x = a_1 + k_1 m_1 = a_1 + \frac{a_2 - a_1}{d}x_0m_1 x = a 1 + k 1 m 1 = a 1 + d a 2 − a 1 x 0 m 1
于是我们构造出了一个符合条件的解,下面我们考虑构造出整个解系 :
我们有定理 :
若有特解 x ′ x' x ′ ,那么上述两个线性同余方程构成的同余方程组的通解是 : x ′ + k ⋅ lcm ( m 1 , m 2 ) x'+k\cdot \text{lcm}(m_1,m_2) x ′ + k ⋅ lcm ( m 1 , m 2 ) ,也就是 :
x ≡ x ′ ( m o d lcm ( m 1 , m 2 ) ) x \equiv x' (\bmod \text{lcm}(m_1,m_2)) x ≡ x ′ ( mod lcm ( m 1 , m 2 ))
这个通解的正确性是显然的,然而我们需要考虑的问题是它是否全面,即为何一个 lcm ( m 1 , m 2 ) \text{lcm}(m_1,m_2) lcm ( m 1 , m 2 ) 当中只会有一个解的问题。
为了解决这个唯一性问题,我们通常采取反证法 : 假设 x , y x,y x , y 都是满足条件的解,然后证明 x = y x = y x = y ,那么就可以证明唯一性。
设上述问题中存在 0 ≤ x , y ≤ lcm ( m 1 , m 2 ) 0 \le x,y \le \text{lcm}(m_1,m_2) 0 ≤ x , y ≤ lcm ( m 1 , m 2 ) ,都使得原同余方程组成立。
不妨设 x ≥ y x \ge y x ≥ y ,那么立即可以发现 :
x − y ≡ 0 ( m o d m 1 ) x - y \equiv 0 (\bmod m_1 \; ) x − y ≡ 0 ( mod m 1 )
x − y ≡ 0 ( m o d m 2 ) x - y \equiv 0 (\bmod m_2 \; ) x − y ≡ 0 ( mod m 2 )
也就是 :
lcm ( m 1 , m 2 ) ∣ ( x − y ) \text{lcm}(m_1,m_2) \mid (x-y) lcm ( m 1 , m 2 ) ∣ ( x − y )
因为 x , y x,y x , y 都是小于 lcm ( m 1 , m 2 ) \text{lcm}(m_1,m_2) lcm ( m 1 , m 2 ) 的数,他们作差也一定小于 lcm ( m 1 , m 2 ) \text{lcm}(m_1,m_2) lcm ( m 1 , m 2 ) ,又有整除,于是 x − y = 0 , x = y x - y = 0,x = y x − y = 0 , x = y ,得证。
则原来两个方程组成的方程组的解为 x ≡ b ( m o d M ) x \equiv b (\bmod M) x ≡ b ( mod M ) ,其中 b = m 1 k 1 + a 1 b = m_1k_1 + a_1 b = m 1 k 1 + a 1 , M = lcm ( m 1 , m 2 ) M = \text{lcm}(m_1,m_2) M = lcm ( m 1 , m 2 )
对于有多个方程的情况,我们使用相同的方法对它进行两两合并,就可以解出同余方程组了。
模板题是P4777
代码如下 :
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6;
int n,x,y,A,B,C;
int m[maxn],a[maxn],ans;
int qmul(int a,int b,int mo){
int ans = 0,base = a;
while(b){
if(b&1) ans = (ans+base) %mo;
base = (base+base) %mo;
b >>= 1;
}
return ans;
}
int exgcd(int a,int b,int &x,int &y) {
if(!b) {
x=1, y=0;
return a;
}
int g = exgcd(b,a%b,x,y);
int tx = x;
x = y;
y = tx-(a/b)*y;
return g;
}
signed main()
{
scanf("%lld",&n);
for(int i = 1; i <= n; i++)
scanf("%lld%lld",&m[i],&a[i]);
for(int i = 2; i <= n; i++) {
A = m[1], B = m[i], C = a[i]-a[1];
C = (C%B+B)%B;
int g = exgcd(A,B,x,y);
x = qmul(x,(C/g),B);
x = (x%B+B)%B;
a[1] = a[1]+ qmul(m[1],x,m[1]*(m[i]/g));
m[1] = m[1]*(m[i]/g);
a[1] = (a[1]%m[1]+m[1])%m[1];
}
printf("%lld",a[1]);
return 0;
}
(代码中的 qmul 是龟速乘)
Lucas定理
译名 : 卢卡斯定理
用于解决大组合数取模问题的定理,要求模数必须为素数。
内容如下 :
( n m ) ( m o d p ) = ( n / p m / p ) × ( n m o d p m m o d p ) ( m o d p ) \binom{n}{m} ( \bmod p \; ) = \binom{n/p}{m/p} \times \binom{n \bmod p}{m \bmod p} \; ( \bmod p \; ) ( m n ) ( mod p ) = ( m / p n / p ) × ( m mod p n mod p ) ( mod p )
实现
代码通常这样写 :
ll lucas(ll n,ll m,ll p)
{
if(m == 0) return 1ll;
return C(n % p,m % p,p) * lucas(n / p,m / p,p) % p;
}
其中 C C C 是求组合数的函数,它的实现方式由题目数据范围而定。
时间复杂度是 O ( f ( p ) + g ( n ) log n ) O(f(p)+g(n) \log \; n) O ( f ( p ) + g ( n ) log n ) ,其中 f ( n ) f(n) f ( n ) 是预处理组合数的复杂度, g ( n ) g(n) g ( n ) 是单次求组合数的复杂度。
证明
先推荐一篇写得很好的博客一份关于Lucas定理的简要证明 (我就是从这看懂的)
首先需要两个引理 :
引理一
p p p 为质数,对于任意的 k ∈ [ 1 , p − 1 ] k \in [1,p-1] k ∈ [ 1 , p − 1 ] ,我们有 :
C p k ≡ 0 ( m o d p ) C_p^k \equiv 0 \; ( \bmod p \; ) C p k ≡ 0 ( mod p )
证明 :
C p k = p ! k ! × ( p − k ) ! C_p^k = \frac{p!}{k! \times (p-k)!} C p k = k ! × ( p − k )! p !
因为 p ⊥ k p \bot k p ⊥ k ,所以分子中不含有 p p p 和 p p p 的真因数,即不可约去 p p p 这一项,于是原式的值有因子 p p p ,在模 p p p 意义下值为 0 0 0
引理二
p p p 为质数,则对于任意正整数 x x x 都有 :
( 1 + x ) p ≡ 1 + x p ( m o d p ) (1+x)^p \equiv 1 + x^p \; ( \bmod p \; ) ( 1 + x ) p ≡ 1 + x p ( mod p )
证明需要用到二项式定理 :
( 1 + x ) p ≡ ∏ i = 0 p c p i ⋅ x i ( m o d p ) (1 + x) ^ p \equiv \prod_{i=0}^p c_p^i \cdot x^i \; ( \bmod p \; ) ( 1 + x ) p ≡ i = 0 ∏ p c p i ⋅ x i ( mod p )
由引理一,可以约去 C p 1 ∼ C p p − 1 C_p^1 \sim C_p^{p-1} C p 1 ∼ C p p − 1 项,于是就有 :
( 1 + x ) p ≡ 1 + x p ( m o d p ) (1 + x) ^ p \equiv 1 + x^p \; ( \bmod p \; ) ( 1 + x ) p ≡ 1 + x p ( mod p )
于是我们利用以上两个引理来证明Lucas定理 :
由二项式定理,有 :
( 1 + x ) n ≡ ∑ i = 0 n C n i ⋅ x i ( m o d p ) (1 + x)^n \equiv \sum_{i = 0}^nC_n^i \cdot x_i \;( \bmod p \; ) ( 1 + x ) n ≡ i = 0 ∑ n C n i ⋅ x i ( mod p )
我们使用带余除法,也就是 n = q n ⋅ p + r n , m = q m ⋅ p + r m n = q_n \cdot p + r_n , m = q_m \cdot p + r_m n = q n ⋅ p + r n , m = q m ⋅ p + r m ,那么就有 :
( 1 + x ) n ≡ ( 1 + x ) q n ⋅ p + r n ≡ [ ( 1 + x ) p ] q n ⋅ ( 1 + x ) r n ( m o d p ) (1+x)^n \equiv (1+x) ^ {q_n \cdot p + r_n} \equiv [(1+x)^p]^{q_n} \cdot (1+x)^{r_n} \; ( \bmod p \; ) ( 1 + x ) n ≡ ( 1 + x ) q n ⋅ p + r n ≡ [( 1 + x ) p ] q n ⋅ ( 1 + x ) r n ( mod p )
用二项式定理展开 :
∑ i = 0 n C n i ⋅ x i ≡ ( ∑ j = 0 q n C q n j ⋅ x p ⋅ j ) ( ∑ k = 0 r n C r n k ⋅ x k ) \sum_{i=0}^nC_n^i \cdot x_i \equiv \left( \sum_{j = 0}^{q_n} C_{q_n}^j \cdot x ^ {p \cdot j} \right ) \left ( \sum_{k = 0}^{r_n} C_{r_n}^k \cdot x ^ k \right ) i = 0 ∑ n C n i ⋅ x i ≡ ( j = 0 ∑ q n C q n j ⋅ x p ⋅ j ) ( k = 0 ∑ r n C r n k ⋅ x k )
此时我们观察这个式子 :
C n m C_n^m C n m 就是左式 x m x^m x m 项的系数,它唯一对应着右侧 j = p m , k = r m j = p_m,k = r_m j = p m , k = r m 的情况,因为只有此时能乘出来 x p ⋅ p m ⋅ x r m = x m x^{p \cdot p_m} \cdot x^{r_m} = x^m x p ⋅ p m ⋅ x r m = x m
我们把 j , k j,k j , k 的取值代入,就有了 :
C n m ≡ C q n q m ⋅ C r n r m ≡ C ⌊ n p ⌋ ⌊ m p ⌋ ⋅ C n m o d p m m o d p ( m o d p ) C_n^m \equiv C_{q_n}^{q_m} \cdot C_{r_n}^{r_m} \equiv C_{\lfloor \frac{n}{p} \rfloor} ^ {\lfloor \frac{m}{p} \rfloor} \cdot C_{n \bmod p} ^ {m \bmod p} \; (\bmod p\; ) C n m ≡ C q n q m ⋅ C r n r m ≡ C ⌊ p n ⌋ ⌊ p m ⌋ ⋅ C n mod p m mod p ( mod p )
于是Lucas定理得证
扩展Lucas定理
(exLucas)
Lucas定理要求模数 p p p 必须为素数,对于不是素数的模数 p p p ,我们可以使用exLucas。
(以下部分来自marchkid_joe):
引入
在解决问题时,会遇到模数不是质数的情况,便又有了拓展卢卡斯的定理(EXLucas)。(拓展卢卡斯和卢卡斯没关系)。
仍然是这个问题,出题人又不保证 p ∈ p r i m e p\in prime p ∈ p r im e 。
C n m m o d p p ∈ N ∗ C_{n}^{m}\bmod p
\qquad
p\in N^* C n m mod p p ∈ N ∗
具体流程
(可以看出 ExLucas 确实和 Lucas 一点关系没有。)
( 1 ) (1) ( 1 ) .对于模数 P P P 根据唯一分解定理 ,我们可以把 P P P 拆为几个质数相乘的形式。
P = ∏ i = 1 n p i k i P=\displaystyle\prod_{i=1}^{n} p_i^{k_i} P = i = 1 ∏ n p i k i
( 2 ) (2) ( 2 ) .因为现在拆成的几个质数的乘积之间一定两两互质,根据中国剩余定理 ,可以列出下面的式子:
{ x ≡ C n m ( m o d p 1 k 1 ) x ≡ C n m ( m o d p 2 k 2 ) ⋮ x ≡ C n m ( m o d p n k n ) \begin{cases}
x&\equiv C_n^m(\bmod\,p_1^{k_1})\\
x&\equiv C_n^m(\bmod\,p_2^{k_2})\\
&\vdots\\
x&\equiv C_n^m(\bmod\,p_n^{k_n})\\
\end{cases} ⎩ ⎨ ⎧ x x x ≡ C n m ( mod p 1 k 1 ) ≡ C n m ( mod p 2 k 2 ) ⋮ ≡ C n m ( mod p n k n )
( 3 ) (3) ( 3 ) .解出每一个方程。
( 4 ) (4) ( 4 ) .合并中国剩余定理。
解释流程 (3)
相信大家最疑惑的一定是 ( 3 ) (3) ( 3 ) 吧,我们随便拎出来一个式子:
C n m m o d p k = n ! m ! ( n − m ) ! m o d p k C_n^m\bmod p^k=\frac{n!}{m!(n-m)!}\bmod p^k C n m mod p k = m ! ( n − m )! n ! mod p k
阶乘内可能含有 p p p ,无法求逆元怎么解决呢?
Answer :那就把 p p p 提出来!
举个很经典的栗子
22 ! , p = 3 , k = 2 , p k = 9 22!,p=3,k=2,p^k=9 22 ! , p = 3 , k = 2 , p k = 9
22 ! ≡ ( 1 × 2 × 4 × 5 × 7 × 8 ) × ( 10 × 11 × 13 × 14 × 16 × 17 ) × ( 19 × 20 × 22 ) × ( 3 × 6 × 9 × 12 × 15 × 18 × 21 ) ( m o d 3 2 ) ≡ ( 1 × 2 × 4 × 5 × 7 × 8 ) 2 × ( 19 × 20 × 22 ) × 3 7 ( 1 × 2 × 3 × 4 × 5 × 6 × 7 ) ( m o d 3 2 ) \begin{aligned}
22!
&\equiv(1\times 2\times 4\times 5\times 7\times 8)\\
&\times (10\times 11\times 13\times 14\times 16\times 17)\\
&\times (19\times 20\times 22)\\
&\times (3\times 6\times 9\times 12\times 15\times 18\times 21)(\bmod\,3^2)\\
&\equiv(1\times 2\times 4\times 5\times 7\times 8)^2\\
&\times (19\times 20\times 22)\\
&\times 3^7(1\times 2\times 3\times 4\times 5\times 6\times 7)(\bmod\,3^2)\\
\end{aligned} 22 ! ≡ ( 1 × 2 × 4 × 5 × 7 × 8 ) × ( 10 × 11 × 13 × 14 × 16 × 17 ) × ( 19 × 20 × 22 ) × ( 3 × 6 × 9 × 12 × 15 × 18 × 21 ) ( mod 3 2 ) ≡ ( 1 × 2 × 4 × 5 × 7 × 8 ) 2 × ( 19 × 20 × 22 ) × 3 7 ( 1 × 2 × 3 × 4 × 5 × 6 × 7 ) ( mod 3 2 )
我们可以发现这样一个规律:
可以将式子拆为四部分
提出来的 p x , x = ⌊ n p ⌋ p^x,x={\lfloor\frac{n}{p}\rfloor} p x , x = ⌊ p n ⌋ 。
含有质因子为 p p p 的数每个都提出一个 p p p 后变成了 ⌊ n p ⌋ ! {\lfloor\frac{n}{p}\rfloor}! ⌊ p n ⌋ ! 。
不含质因子但可以凑成以 p k p^k p k 为单位的 ⌊ n p k ⌋ {\lfloor\frac{n}{p^k}\rfloor} ⌊ p k n ⌋ 组数。
剩下的数字。
化成一个恶心的式子:
n ! = ⌊ n p ⌋ ! × p ⌊ n p ⌋ × ( ∏ i = 1 ∧ i ∤ p p k i ) ⌊ n p k ⌋ × ( ∏ i = p k × ⌊ n p k ⌋ + 1 ∧ i ∤ p n i ) \begin{aligned}
n!={\lfloor\frac{n}{p}\rfloor}!\times p^{\lfloor\frac{n}{p}\rfloor}\times ({\displaystyle\prod_{i=1\land i\nmid p}^{p^k}i})^{\lfloor\frac{n}{p^k}\rfloor}\times ({\displaystyle\prod_{i=p^k\times{\lfloor\frac{n}{p^k}\rfloor}+1\land i\nmid p}^{n}i})
\end{aligned} n ! = ⌊ p n ⌋ ! × p ⌊ p n ⌋ × ( i = 1 ∧ i ∤ p ∏ p k i ) ⌊ p k n ⌋ × ( i = p k × ⌊ p k n ⌋ + 1 ∧ i ∤ p ∏ n i )
我们发现 ⌊ n p ⌋ ! {\lfloor\frac{n}{p}\rfloor}! ⌊ p n ⌋ ! 可以继续递归求解 。
我们定义 f ( n ) f(n) f ( n ) 为提完所有 p p p 以后阶乘之和,定义函数 g ( n ) g(n) g ( n ) 为从 n ! n! n ! 提出来的 p p p 的次幂。同样可以递归求解。
f ( x ) = f ( ⌊ n p ⌋ ) × ( ∏ i = 1 ∧ i ∤ p p k i ) ⌊ n p k ⌋ × ( ∏ i = p k × ⌊ n p k ⌋ + 1 ∧ i ∤ p n i ) f(x)={f(\lfloor\frac{n}{p}\rfloor})\times({\displaystyle\prod_{i=1\land i\nmid p}^{p^k}i})^{\lfloor\frac{n}{p^k}\rfloor}\times({\displaystyle\prod_{i=p^k\times {\lfloor\frac{n}{p^k}\rfloor}+1\land i\nmid p}^{n}i}) f ( x ) = f (⌊ p n ⌋ ) × ( i = 1 ∧ i ∤ p ∏ p k i ) ⌊ p k n ⌋ × ( i = p k × ⌊ p k n ⌋ + 1 ∧ i ∤ p ∏ n i )
g ( n ) = ⌊ n p ⌋ + g ( ⌊ n p ⌋ ) g(n)=\lfloor\frac{n}{p}\rfloor+g(\lfloor\frac{n}{p}\rfloor) g ( n ) = ⌊ p n ⌋ + g (⌊ p n ⌋)
对每一个阶乘进行操作,就得到了这个式子:
n ! p x m ! p y × ( n − m ) ! p z × p x − y − z ( m o d p k ) \frac{\frac{n!}{p^x}}{\frac{m!}{p^y}\times\frac{(n-m)!}{p^z}}\times p^{x-y-z}(\bmod\,p^k) p y m ! × p z ( n − m )! p x n ! × p x − y − z ( mod p k )
f ( n ) f ( m ) f ( n − m ) p g ( n ) − g ( n − m ) − g ( m ) ( m o d p k ) \frac{f(n)}{f(m)f(n-m)}p^{g(n)-g(n-m)-g(m)}(\bmod\,p^k) f ( m ) f ( n − m ) f ( n ) p g ( n ) − g ( n − m ) − g ( m ) ( mod p k )
此时我们发现:我们已经从所有阶乘中提尽了 p p p 。
∵ gcd ( p k , f ( m ) ) = 1 ∧ gcd ( p k , f ( n − m ) ) = 1 \because
\gcd(p^k,f(m))=1
\land
\gcd(p^k,f(n-m))=1 ∵ g cd( p k , f ( m )) = 1 ∧ g cd( p k , f ( n − m )) = 1
∴ f ( m ) , f ( n − m ) \therefore f(m),f(n-m) ∴ f ( m ) , f ( n − m ) 存在模 p k p^k p k 意义下的逆元。
其中 g ( m ) + g ( n − m ) ⩽ g ( n ) g(m)+g(n-m)\leqslant g(n) g ( m ) + g ( n − m ) ⩽ g ( n ) 一定成立。
简单说明一下,已知 n > m n\gt m n > m ,先将 n ! n! n ! 的前 m m m 项消掉,剩下 n − m n-m n − m 项为 n × ( n − 1 ) × … × ( n − m + 1 ) n\times (n-1)\times …\times (n-m+1) n × ( n − 1 ) × … × ( n − m + 1 ) ,所以这剩下的 n − m n-m n − m 项一定不小于 ( n − m ) ! (n-m)! ( n − m )! ,因此 g ( m ) + g ( n − m ) ⩽ g ( n ) g(m)+g(n-m)\leqslant g(n) g ( m ) + g ( n − m ) ⩽ g ( n ) 。
已经解决了最困难的一步,中国剩余定理等一些简单的东西可以参考前文。
成功了!
(引用完)
常用变换
注 : 由于篇幅限制,以下关于狄利克雷卷积和莫比乌斯反演的例题及解析都放在了 莫比乌斯反演总结 一文中,那是对这一部分内容的专题强化。
Dirichlet卷积
译名就是狄利克雷卷积
1.定义 :
对于两个数论函数 f ( x ) , g ( x ) f(x),g(x) f ( x ) , g ( x ) ,定义他们的卷积为
( f ∗ g ) ( n ) = ∑ d ∣ n f ( d ) ⋅ g ( n d ) (f*g)(n) = \sum_{d \mid n} f(d) \cdot g(\frac{n}{d}) ( f ∗ g ) ( n ) = d ∣ n ∑ f ( d ) ⋅ g ( d n )
2.性质:
交换律: f ∗ g = g ∗ f f \ast g = g \ast f f ∗ g = g ∗ f
结合律: ( f ∗ g ) ∗ h = f ∗ ( g ∗ h ) ( f \ast g ) \ast h = f \ast ( g \ast h ) ( f ∗ g ) ∗ h = f ∗ ( g ∗ h )
分配律: f ∗ ( g + h ) = f ∗ g + f ∗ h f \ast ( g + h ) = f \ast g + f \ast h f ∗ ( g + h ) = f ∗ g + f ∗ h
单位元: ε \varepsilon ε 表示 [ x = 1 ] [x=1] [ x = 1 ] ,满足对任意函数 有 ε ∗ f = f \varepsilon * f = f ε ∗ f = f
对积性函数: 若 f f f 为积性, g g g 为积性,则 f ∗ g f*g f ∗ g 也为积性
对积性函数: 若 f f f 为积性, f ∗ g f*g f ∗ g 也为积性,则 g g g 为积性
3.常见卷积:
其中涉及到的数论函数详见数论函数总结
f ∗ 1 = ∑ d ∣ n f ( d ) f*1 = \sum_{d \mid n} f(d) f ∗ 1 = d ∣ n ∑ f ( d )
i d k ∗ 1 = σ k id_k*1 = \sigma_k i d k ∗ 1 = σ k
φ ∗ 1 = i d \varphi * 1 = id φ ∗ 1 = i d
μ ∗ 1 = ε \mu * 1 = \varepsilon μ ∗ 1 = ε
i d ∗ μ = φ id * \mu = \varphi i d ∗ μ = φ
1 ∗ 1 = τ 1 * 1 = \tau 1 ∗ 1 = τ
若 F = 1 ∗ f F = 1*f F = 1 ∗ f 则有
f = μ ∗ F f = \mu * F f = μ ∗ F
莫比乌斯反演
1.定义 : 对于以下求和函数 :
F ( n ) = ∑ d ∣ n f ( d ) F(n) = \sum_{d \mid n} f(d) F ( n ) = d ∣ n ∑ f ( d )
有 :
f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n) = \sum_{d\mid n}\mu(d)F(\frac{n}{d}) f ( n ) = d ∣ n ∑ μ ( d ) F ( d n )
2.莫比乌斯等式 :
ε ( n ) = ∑ d ∣ n μ ( d ) \varepsilon(n) = \sum_{d \mid n}\mu(d) ε ( n ) = d ∣ n ∑ μ ( d )
(即 μ ∗ 1 = ε \mu*1=\varepsilon μ ∗ 1 = ε )
3.性质 : 若 F ( n ) F(n) F ( n ) 为积性函数,那么 f ( n ) f(n) f ( n ) 也为积性函数。
年少不知学姐(长)好,清北学堂泪两行