aka 高中數學 in 資訊
競賽數學主要分 ACGN 四大類
Algebra 代數
Combinatory 組合
Geometry 幾何
Number theory 數論
不是 Animation, Comic, Game, Novel 啦
資訊用到的數學
\(C \approx N > A > G\)
然後要會一點向量、線性代數、群論
a 與 b 在模 p 下同餘若且唯若 (a-b)%p == 0
這裡的 p 不一定是質數
const int mod=998244353;
void add(int& x,int y){
x+=y;
x-=mod*(x>=mod);
x+=mod*(x<0);
}
int mul(int x,int y){
return 1ll*x*y%mod;
}
在模質數底下,不能整除怎麼辦
\(\frac{x}{y} = z \implies x \equiv y \cdot z \pmod p\)
假設我們有 \(y \cdot b \equiv 1 \pmod p\)
那麼 \( x \cdot b \equiv b \cdot y \cdot z \equiv z \pmod p\)
也就是說 \( z \equiv x \cdot b \pmod p \)
這樣就可以算了
問題就是要怎麼算出那個 b
有三種方法
$$ a^{p-1} \equiv 1 \pmod p$$
也就是說 \( a \cdot a^{p-2} \equiv 1 \pmod p\)
代表 \(b = a^{p-2}\)
直接用快速冪做就好了
\( a^n = (a^{n/2})^2 \cdot a [a\%2==1] \)
O(logn)
int inv(int x){
return x==1?1:mul(mod-mod/x,inv(mod%x));
}
據說是 O(logn)
我不會證但是沒有出包過
實作簡單
對於所有整數 \(a,b\) 存在無限多組整數 \(x,y\) 滿足 $$ ax + by = gcd(a,b) $$
假設我們有了 \( bx' + (b\%a)y' = 1\)
要怎麼推出 \(ax + by = 1\)的解
注意到 \(a\%b = a - \lfloor \frac{a}{b} \rfloor \cdot b\)
$$bx' + (a\%b) y' = 1 $$
$$ bx' + (a - \lfloor \frac{a}{b} \rfloor b)y' = 1 $$
$$ ay' + b(x' - \lfloor \frac{a}{b} \rfloor y') = 1$$
是唯一能用在合數的模逆元方法
輾轉相除法
或是有酷酷的內建函式 __gcd 可以用
const int mod=998244353;
void add(int& x,int y){
x+=y;
x-=mod*(x>=mod);
x+=mod*(x<0);
}
int mul(int x,int y){
return 1ll*x*y%mod;
}
int po(int x,int y){
int z=1;
while(y){
if(y&1){
z=mul(z,x);
}
x=mul(x,x);
y>>=1;
}
return z;
}
int inv(int x){
return po(x,mod-2);
}
int inv(int x){
return x==1?1:mul(mod-mod%x,inv(mod%x));
}
add(x,1);
x=mul(x,2);
__gcd(3,5);
模逆元練習
從 1 掃到 \( \sqrt n\) ,如果裡面有整數是因數就不是質數,反之則是
照上面的作法會是 O(n^1.5)
改進一下
從 1 到 n 掃過一遍,每次更新他的所有倍數
沒被更新過的就是質數
\( O( \frac{n}{1} + \frac{n}{2} + \dots + \frac{n}{n}) = O(n log(n)) \)
因數篩
只跑過質數的倍數
\( O( \frac{n}{2} + \frac{n}{3} + \dots )= O(n loglog(n)) \)
上一張的可以用在找出一個數的所有因數
由此也可得 1 到 n 所有數的因數數量和 = O(nlogn)
如果能讓每個數都被篩過一次,那就可以 O(n) 算完了
所以我們會想要讓每個合數被他的最小質因數算到
vector<int> vis,pr;
for(int i=2;i<n;i++){
if(!vis[i]){
pr.push_back(i);
}
for(auto h:pr){
if(h*i>n){
break;
}
vis[h*i]=1;
if(i%h==0){
break;
}
}
}
歐拉函數 \(\varphi(n)\) 代表 n 以下有多少數與 n 互質
有積性
vector<int> vis,pr,phi;
for(int i=2;i<n;i++){
if(!vis[i]){
pr.push_back(i);
phi[i]=i-1;
}
for(auto h:pr){
if(h*i>n){
break;
}
vis[h*i]=1;
if(i%h==0){
phi[i*h]=h*phi[i];
break;
}
else{
phi[i*h]=phi[h]*phi[i];
}
}
}
組合數 \(C^n_k\)
算法:主要有三種
在 n 個裡面取 k 個的方法數
\(n_i\) 跟 \(k_i\) 分別是 n 跟 k 轉成 p 進位每一個位的位元
例題:ARC 137 D
高斯消去
把對角線以下的消掉