---恢复内容开始---
今天江哥来个给我们讲一些数学方面的小知识...小小总结一下!
1. exgcd().
1 inline ll exgcd(ll a,ll b,ll c){ 2 return c % a ? (exgcd(b % a, a, ((-c % a) + a) % a) * b + c) / a : c / a; 3 }
江哥的神代码... 非常简单直接就能求逆元.
2.线筛 prime && phi && 逆元
1 inline void sieve(){ 2 for(ll i = 2; i < maxn; ++i) 3 if(!vis[i]){ 4 prime[++sz] = i; 5 for(ll j = i*i; j < maxn; j += i) vis[j] = 1; 6 } 7 } 8 9 10 inline void get_phi(){ 11 phi[1] = 1; 12 for(int i = 2; i < maxn ; ++i){ 13 if(!vis[i]){ prime[++sz] = i; phi[i] = i-1; } 14 for(int j = 1; j <= sz && prime[j] * i < maxn; ++j){ 15 vis[prime[j] * i] = 1; 16 phi[prime[j] * i] = phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]); 17 } 18 } 19 }
某些情况下必须快速筛phi吧.
因为 phi 函数是一个积性函数, 我们从 phi 函数的计算式来考虑, 对于一个数, N = a * p, 如果 a % p == 0 那么 phi(N) = phi(a) * p, 否则 phi(N) = phi(a) * (p - 1).
然后线筛逆元的想法是 , inv(n!) = inv((n-1)!) * n... 然后我们就能够线性递推...进而推出 1~n 的逆元.
3. CRT
CRT 是求一个同余方程组的解 x ≡ bi (mod pi) ... 以前一直是写的暴力的 CRT(暴力做加法....).
但是我们如果这样想..... x = a1 + a2 + a3, 其中只有 ai 对方程 i 有贡献 (ai % pj != i)== 0
这个问题就好办了, 用 exgcd 求出每个ai, 然后求和就能得到一个 x 的解.
4. Lucas && ex_Lucas.
Lucas: C(n,m) % p == C(n % p, m % p) * Lucas(n / p, m / p);
ex_Lucas: 主要思想是将 C(n,m) 中的 模数 p 的因子提出来, 然后再求逆元...(p 不能太大)
5. Bs_Gs()
求离散对数 ax ≡ b (mod p).
hash x = [1, √p], 然后 b 每次乘上 inv(a√p ), 再去 hash 表中找.
Bs_Gs() 能够拓展.
6. 离散开方
xa ≡ b (mod p).
我们在这里使用原根 g 来表示 x 以及 b.(原根的定义自行 Wiki)
先计算出 p 的原根 g 然后用Bs_Gs()计算指数.
xa ≡ b (mod p) => (gi)a ≡ gj (mod p).根据费马小定理 ap - 1 ≡ 1 (mod p).
=> i * a ≡ j (mod p - 1).
求解线性模方程用 exgcd 就 ok 了.
7. FFT
大体思路:
利用多项式的点值表示来计算乘积,运用分治的思想进行快速插值与逆差值.
待补全....