數論 I
5th Nov. 2019
可能大家都覺得很簡單
那就再聽一次吧!
以資訊方法解決數論問題
Today
暖身
有 \( n \) 袋米編號依序為 \( 1 \) 到 \(n \) ,其中一袋裝著全部都是壞掉的米,另外 \( n - 1 \) 袋裝的都是正常的米。已知一粒正常的米重\( 1 \) 單位,而一粒爛掉的米重 \( 0.1 \) 單位。現在,你有一個電子秤(可以告訴你重量)但是只能秤一次,請問你要怎麼知道爛掉的米是哪一袋?假設一袋的米夠多可以一直拿而不會取盡。
暖身 —— 解答
從第 \( i \) 袋取 \( i \) 粒米
設爛掉的是第\( k \)袋,則重量 \( \left( \sum^n_{i = 1} i \right) - 0.9k\)
可以直接算!
同餘
定義 —— 同餘
我們定義同餘 \( a \equiv b \pmod{m} \)若且唯若\( a \) 取\( m \) 的餘數等於 \( b \) 取\( m \) 的餘數
Ex. \( 5 \equiv 7 \pmod 2\) 、\( 7122 \equiv 12 \pmod 9 \)
定義 —— 整除
我們定義整除 \( a \vert b \)若且唯若存在一個整數\( k \) s.t. \( b = ak \)
Ex. \( 123 \vert 0 \) 、\( 1 \vert 12 \) 、\( -2 \vert 226 \) 皆為真
同餘的性質
- 可以加:\( a \equiv b \pmod m \iff a + c \equiv b + c \pmod m \)
- 可以乘:\( a \equiv b \pmod m \implies ac \equiv bc \pmod m \)
不是都能除!
反例: \( 6 \equiv 12 \pmod 3 \) 但是\( 1 \not \equiv 2 \pmod 3 \)
取餘數:扣
a % b
就醬
UVa 10127 - Ones
給定一個數字 \( N \),定義 \(f(N) \) 為 「將\(1, 2, \dots, N\)寫在一起所成的數字。例:
\( f(4) = 1234 \),\( f(6) = 123456 \) 。
請問 \( f(N) \) 是否為 \( \text{suum} \) (\(3\)) 的倍數?
( \( N \leq 10^8 \) )
整除
\( \gcd \) 和 \( \text{lcm} \) 函數
來定義一下
就是小學遇過的最大公約數(\( \gcd \))和最小公倍數(\( \text{lcm} \))啦
算數基本定理
(Fundamental Theorem of Arithemetic)
定理:每一個大於\(1\)的正整數都有一個唯一的質因數分解
證明:略
正式定義 \( \gcd \)、\( \text{lcm} \)
令 \( n = \prod^{\infty}_{i = 1} p_i^{\alpha_i} \),\( m = \prod^{\infty}_{i = 1} p_i^{\beta_i} \)
則 \(\gcd(n, m) = \prod^{\infty}_{i = 1} p_i^{\min(\alpha_i, \beta_i)} \)
\(\text{lcm}(n, m) = \prod^{\infty}_{i = 1} p_i^{\max(\alpha_i, \beta_i)} \)
令 \( n = \prod^{\infty}_{i = 1} p_i^{\alpha_i} \),\( m = \prod^{\infty}_{i = 1} p_i^{\beta_i} \)
則 \(\gcd(n, m) = \prod^{\infty}_{i = 1} p_i^{\max(\alpha_i, \beta_i)} \)
\(\text{lcm}(n, m) = \prod^{\infty}_{i = 1} p_i^{\min(\alpha_i, \beta_i)} \)
故 \(\gcd(n, m) \times \text{lcm} (n, m) = \prod^{\infty}_{i = 1} p_i^{\max(\alpha_i, \beta_i) + \min(\alpha_i, \beta_i)} \\ = n \times m\)
計算 \( \gcd \) —— 輾轉相除
給定一組\( (a, b) \),我們想要找到最大的 \( d \) s.t. \( d \vert a \) 且 \( d \vert b \)。
計算 \( \gcd \) —— 輾轉相除
給定一組\( (a, b) \),我們想要找到最大的 \( d \) s.t. \( d \vert a \) 且 \( d \vert b \)。
若 \( d \) s.t. \( d \vert a \) 且 \( d \vert b \),則 \( d \vert (a - b) \)!(假設\(a \geq b\) )
計算 \( \gcd \) —— 輾轉相除
若 \( d \) s.t. \( d \vert a \) 且 \( d \vert b \),則 \( d \vert (a - b) \)!(假設\(a \geq b\) )
若其中一者為 \( 0 \),則答案就是另外一者!
計算 \( \gcd \) —— 輾轉相除
演算法:給定了 \( a \) 和 \( b\) ,不斷拿小的減大的,直到其中一者為 \( 0 \) 或變得比另外一者更小。
最差複雜度:若小的為 \( \text{qlig} \),則會跑另外一個數字(設為 \( N \) ) 次,複雜度 \( O(N) \)!
超爛...
要減就減到變小啊 = =
那到什麼時候才會變小?
取餘數!
若 \( a \geq b \),與其一直算 \( a - b \),不如直接 \( a \% b \) 比較快!
int gcd(int a, int b){
while(b > 0){
a %= b;
swap(a, b);
}
return a;
}
遞迴寫法
int gcd(int a, int b){
return (!b ? a : gcd(b, a % b));
}
UVa 412 - Pi
就是一直算\(\gcd\)
一直算\(\gcd\)
一直算\(\gcd\)
一直算\(\gcd\)
一直算\(\gcd\)
UVa 10622 - Perfect P-th Powers
給定一個小於\(\text{int}\)範圍且大於\(2\)的數字\(x\),請求一個最大的正整數\(p\)使得存在一個正整數\(b\)使得
$$x = b^p$$
模下次方
計算 \( a^x \pmod m \)
最簡單的方法
inline int modexp(int a, int b, int m){
int ans = 1;
for(int i = 0; i < b; i++){
ans = ans * a % m;
}
return ans;
}
計算 \(a^b \pmod m \) 需要 \( O(b) \) !
超爛啊,可不可以壓啊?
分而治之
想要計算 \( a^x \),若知道\( t= a^{ \lfloor \frac{x}{2} \rfloor } \),那:
- 若 \(x\) 為奇數,則 \(a^x = t^2 \times a \)
- 否則 \(a^x = t^2\)
只會計算 \(a, a^2, a^4, \dots, a^{2^{\log x}} \),故複雜度變成 \(O(\log n) \)!
長這樣(遞迴):
int modexp(int b, int e, int m){
if(!b) return 0;
if(!e) return 1;
int res = modexp(b, e/2, m);
res = res * res % m;
if(e % 2) res = res * b % m;
return res;
}
長這樣(迭代):
int modexp(int b, int e, int m){
int res = 1, current = 1;
for(int i = 0; (1LL << i) <= e; i++){
if((1LL << i) & e){
res = res * current % m;
}
current = current * current % m;
}
}
矩陣冪
若有一個 \(n \times m\)的矩陣\(A\),和一個\(m \times k\)的矩陣\(B\),則他們的積會是一個\(n \times k\)的矩陣\(C\),元素定義如下:
$$C_{ij} = \sum^{k}_{t = 1} A_{it}B_{tj}$$
矩陣快速冪
對於一個\(n \times n\)的矩陣\(A\)和一個正整數\(x\),我想要求\(A^x\)。
快速冪!
\( O(n^3 \log x) \)
模下的線性方程
なに???
模數下的線性方程
\( ax + b \equiv 0 \pmod m\)
我們想要解這個:
模數下的線性方程
\( ax \equiv -b \pmod m\)
不能除怎麼辦?
Money 元
模逆元
對於一個數字 \( a \) 和一個模數 \( m \), \( a\) 的模逆元 \( a^{-1} \) 就是滿足
- \( 0 < a^{-1} < m \)
- \( a^{-1} \cdot a \equiv 1 \pmod m \)
的數字
不一定存在!條件: \( \gcd (a, m) = 1 \)
費馬小定理
給定一個質數 \( p \) 和一個小於 \(p\) 的數字 \(a \) ,恆有
\( a^{p - 1} \equiv 1 \pmod p \)
證明:
首先列出\( a, 2a, \dots, (p - 1)a \)共\( (p - 1)\)個數字。
若 \( sa \equiv ra \pmod p \)則一定有 \( p | (s - r) a \), \(p | (s -r) \) 或 \( p | a \)。但這兩者都比 \( p\)小,所以 \(s - r = 0\),也就是那\(p - 1\)個數字為一個完全剩餘系。
證明:
將那些數字乘起來,則:
$$a \cdot 2a \cdot 3a \dots \cdot (p - 1)a \equiv 1 \cdot 2 \cdot 3 \dots \cdot (p - 1) \pmod p$$
$$(p - 1)! \cdot a^{p - 1} \equiv (p - 1)! \pmod p$$
\((p - 1)!\)與\(p\)互質,所以可以除
$$ a^{p - 1} \equiv 1 \pmod p $$
質數下的模逆元
由於費馬小定理,$$a^{p - 1} \equiv a \cdot a^{p - 2} \equiv 1 \pmod p $$
故計算 \( a^{p - 2} \) 就可以計算模逆元!
非質數的狀況
擴展歐幾里德!
(變強版輾轉相除)
貝祖定理:對於兩個\(a, b\),一定存在無限多組\(x, y \in \mathbb{Z} \) s.t. \(ax + by = \gcd(a, b) \)
證明:略。爽。
非質數的狀況
擴展歐幾里德!
(變強版輾轉相除)
假設 \( \gcd(a, m) = 1 \),我們想要找到一個 \(b\) s.t. \(ab \equiv 1 \pmod m\)
非質數的狀況
擴展歐幾里德!
(變強版輾轉相除)
$$ab \equiv 1 \pmod m$$
代表存在一個 \(k\) s.t.
$$ab - 1 = mk \implies ab - mk = 1$$
輸入 \((a, m)\),得到\(b, k\)即可!
遞迴看看
想要求\(ax + by = 1\)的解,若知\((x', y')\)滿足
$$bx' + (a - \lfloor \frac{a}{b} \rfloor b)y' = 1$$要怎麼得到解?
遞迴看看
想要求\(ax + by = 1\)的解,若知\((x', y')\)滿足
$$bx' + (a - \lfloor \frac{a}{b} \rfloor b)y' = 1$$要怎麼得到解?
祕技:等量公理
遞迴看看
$$bx' + (a - \lfloor \frac{a}{b} \rfloor b)y' = 1$$
$$ay' + b\left( x' - \lfloor \frac{a}{b} \rfloor y' \right) = 1$$
實作
void extgcd(int a, int b, int &x, int &y, int &d){
if(!b){
d = a;
x = 1;
y = 0;
return;
} else {
extgcd(b, a % b, x, y, d);
int newX, newY;
newX = y;
newY = x - a/b * y;
x = newX;
y = newY;
return;
}
}
參數才會爽
補充:得到其他解
若已經知道 \(ax + by = \gcd(a, b)\),則對於任何一個\(k \in \mathbb{Z} \),\((x', y') = (x + bk, y - ak)\)也會是一組解
質數篇
Optimus Prime
優化質數?

求 \(N\) 以下的所有質數
大家都會\(O(N^2)\)吧...
Sieve of Ἐρατοσθένης
埃拉托斯特尼篩法

Sieve of Ἐρατοσθένης
埃拉托斯特尼篩法
演算法:一開始所有的數字都是質數。從\(2\)開始,將大於它其所有的倍數都標示為不是質數。
正確性:一個質數不會被比他前面的數字篩到,因為它不是任何一個比它小的數字的倍數!
Code
簡單明瞭
const int maxN = 1e5;
bool isPrime[maxN];
inline void sieve(){
for(int i = 0; i < maxN; i++) isPrime[i] = true;
isPrime[0] = isPrime[1] = false;
for(int i = 2; i < maxN; i++){
for(int j = 2 * i; j < maxN; j += i)
isPrime[j] = false;
}
}
複雜度 + 優化
複雜度:時間為
\(\sum^{N}_{k = 1} \frac{N}{k}\),為 \(O(N \log N)\)
優化:
-
可以遇到質數再開始篩!
-
\( j\) 不用從 \(2i\) 開始跑,可以從\(i^2\)!
複雜度 + 優化
-
可以遇到質數再開始篩!
-
\( j\) 不用從 \(2i\) 開始跑,可以從\(i^2\)!
質數倒數和更小:
$$\sum_{p \leq n} \frac{1}{p} = O(\log\log n)$$
故演算法為 \(O(N \log \log N)\)!
線。性。篩。
by Euler
邁向真線性
我們想要每一個合數都被篩掉一次!
每一個合數\(N\)都有一個最小質因數\(p_{\min} \),我們想要在\(i = \frac{N}{p_{\min}}\)的時候篩掉
邁向真線性
若目前在\(i\),若\(i\)未被篩掉,則其為質數;也維護一個目前所篩過的質數與之比對。對於每一個質數\(p\):
-
若\(p \times i > N \)直接跳出
-
則\(p \times i \)不是質數,且\(p\)為\(ip\)的最小質因數
-
若\(i\)為\(p\)的倍數,則跳出。
邁向真線性
若\(i\)為\(p\)的倍數,則跳出。
因為\(p\)就會是\(i\)的最小質因數了(依序枚舉質數呀,第一個遇到的就是最小),所以之後的數字都會被\(p\)篩掉,不用急!
複雜度 \( O(N) \)!!!
扣的
const int maxN = 1e5;
bool isPrime[maxN];
vector<int> primes;
inline void getPrime(){
for(int i = 0; i < maxN; i++) isPrime[i] = true;
for(int i = 2; i < maxN; i++){
if(isPrime[i]) primes.push_back(i);
for(int p : primes){
if(i * p > maxN) break;
isPrime[i * p] = false;
if(!(i % p)) break;
}
}
}
TIOJ 1668 - 分組編隊
給定兩個數字\(l, r\),請求有幾個在\([l, r]\)的質數?(保證
\( 1 \leq l \leq r \leq 2^{31} - 1\)
\(r - l \leq 2 \times 10^5 \)
中國剩餘定理
韓信點兵
《孫子算經》
下卷第二十六題 · 物不知數
「有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。問物幾何?」
有一個數字 \(x \)
除\(3\)餘\(2\)
除\(5\)餘\(3\)
求 \(x\)?
除\(7\)餘\(2\)
$$ x \equiv 2 \pmod 3 $$
$$ x \equiv 3 \pmod 5 $$
$$ x \equiv 2 \pmod 7 $$
如果只有兩條式子會不會?
$$ x \equiv a_1 \pmod {m_1}$$
$$ x \equiv a_2 \pmod {m_2}$$
$$x = a_1 \cdot m_2 \cdot (m_2^{-1} \pmod{m_1}) + a_2 \cdot m_1 \cdot (m_1^{-1} \pmod{m_2})$$
構造解:
模\(m_1\)為\(1\)
模\(m_2\)為\(1\)
另外一邊會消掉!
最後再模\(m_1m_2\)就好
直接推廣一波
$$x \equiv a_i \pmod{m_i}$$
假設有\(n\)條式子,且所有的\(m_i\)皆互質,且滿足:
直接推廣一波
定義\(M_i = \prod_{k = 0, k \not= i}^{n} m_k\),
\(\mu_i = M_i^{-1} \pmod{m_i}\)
則可以知道:\(M_i\mu_i \) 在模 \(m_i\)之下為\(1\),在模其他的\(m_j\)之下為\(0\)。
直接推廣一波
則可以知道:\(M_i\mu_i \) 在模 \(m_i\)之下為\(1\),在模其他的\(m_j\)之下為\(0\)。
故構造:
$$x = \sum_{i = 1}^{n} M_i\mu_i a_i \pmod {\text{lcm}(m_i) }$$
或是用擴展歐幾里德
先看前兩條:
\(x \equiv a_1 \pmod {m_1}\)
\(x \equiv a_2 \pmod {m_2}\)
令\(x = m_1k_1 + a_1 = m_2k_2 + a_2\),則
$$m_1k_1 + a_1 = m_2k_2 + a_2$$
$$m_1k_1 - m_2k_2 = a_2 - a_1$$
或是用擴展歐幾里德
$$m_1k_1 + a_1 = m_2k_2 + a_2$$
$$m_1k_1 - m_2k_2 = a_2 - a_1$$
若\((a_2 - a_1) \not \vert \gcd(m_1, m_2)\)則無解
否則可以解得\(k_1\)的值,然後代回去,得到某種
$$x = A + K \times \text{lcm}(m_1, m_2)$$
變成一條式子:
$$x \equiv A \pmod{\text{lcm}(m_1, m_2)}$$
剩下\(n - 1\)條式子,可以繼續做下去!
方法比較
第一種方法:\(O(N)\),但是不能判斷有沒有解,數字可能會爆
第二種方法:\(O(N \log N)\),能判斷無解,數字不一定會爆但是比較能避免(因為是用\(\text{lcm}\))
ZeroJudge c637
滿滿的糖果屋 #3
裸中國餘數定理
質因數分解
耶
基本作法:
若想要分解\(N\),先建立\(\sqrt{N}\) 以下的所有質數,再一個一個篩。
對於一個數字\(N\),至多一個質因數是大於\(\sqrt{N}\)的。
Code
vector<pair<int, int> > factorize(int n){
vector<pair<int, int> > vec;
pii res;
for(int p : primes){
if(p * p > n) break;
if(!(n % p)){
res.F = p;
res.S = 0;
while(!(n % p)){
res.S++;
n /= p;
}
}
}
if(n > 1) res.push_back({n, 1});
}
UVa 10235 - Simply Emirp
一個數字為「\(\text{Prime}\)」若其為質數;若其反過來寫也是質數,則其為「\(\text{Emirp}\)」。請判斷其為哪一個。
UVa 160 - Factors and Factorials
給定一個數字\(N\),請求\(N!\)的質因數分解為何?(\(N \leq 10^3\))
數論 I
By sean5463
數論 I
- 776