NOIp 基礎數論知識點總結


推薦閱讀 NOIp 數學知識點總結: https://www.cnblogs.com/greyqz/p/maths.html


Basic

常用素數表:https://www.cnblogs.com/greyqz/p/9845627.html

快速冪

int qpow(int x, int y) {
    int res = 1;
    for (; y; x = (ll)x * x % mod, y >>= 1)
        if (y & 1) res = (ll)res * x % mod;
    return res;
}

矩陣快速冪:

struct matrix {
    ll m[100][100];
    matrix operator * (matrix &a) {
        matrix b;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++) {
                b.m[i][j] = 0;
                for (int k = 0; k < n; k++)
                    b.m[i][j] = (b.m[i][j] + m[i][k] * a.m[k][j]) \% mod;
            }
        return b;
    }
} s;

matrix mpow(matrix a, ll k) {
    if (k == 1) return a;
    a = mpow(a, k / 2);
    if (k \% 2) return (a * a) * s;
    else return a * a;
}

matrix a = mpow(s, p);

乘法逆元

眾所周知, 在模意義下沒有標准的除法. 為了表示乘法的逆運算, 我們定義:

\({\rm mod}\ p\) 意義下, \(x\)乘法逆元記為 \(x^{-1}\), 即 \(x\cdot x^{-1}\equiv 1\pmod p\).

由此我們得到 \(\displaystyle \frac{x}{y}\equiv x\cdot y^{-1}\pmod p\).

費馬小定理:對於任意素數 \(p\), 有 \(a^{p-1}\equiv 1\pmod p\).

對費馬小定理變形, 得 \(a\cdot a^{p-2}\equiv 1\pmod p\).

所以 \(a^{p-2}\) 即為 \(a\) 的乘法逆元. 對於非素數 \(p\), 不一定有乘法逆元.

由此, 使用快速冪求解乘法逆元:

inline int qpow(int n, int m, int mod) {
    ll tot = 1;
    for (ll k = n; m; k = k * k % mod, m >>= 1)
    	if (m & 1) tot = tot * k % mod;
    return tot;
}

inline int inv(int x, int mod) {
    return qpow(x, mod - 2);
}

拓展歐幾里得算法用於在線性時間里求解關於 \(x,y\) 的方程 \(ax+by=\gcd(a,b)\) 的一組整數解.

\(b\) 為素數時, \(\gcd(a,b)=1\), 此時有 \(ax\equiv 1\pmod b\). 從而使用拓展歐幾里得算法求解乘法逆元:

void exgcd(const int a, const int b, int &g, int &x, int &y) {
    if (!b) g = a, x = 1, y = 0;
    else exgcd(b, a % b, g, y, x), y -= x * (a / b);
}

inline int inv(const int num) {
    int g, x, y;
    exgcd(num, MOD, g, x, y);
    return ((x % MOD) + MOD) % MOD;
}

以上時間復雜度均為 \(O(\log a)\).

整除

最大公約數

輾轉相除法(歐幾里得算法):

int gcd(int x, int y) {
	return !y ? x : gcd(y, x % y);
}

大整數意義下的快速更相減損術:

bint kgcd(bint a, bint b) {
	if (b == 0) return b;
	if (a < b) return kgcd(b, a);
	if (!(a&1) && !(b&1)) return kgcd(a>>1, b>>1) << 1;
	else if (!(b&1)) return kgcd(a, b>>1);
	else if (!(a&1)) return kgcd(a>>1, b);
	else return kgcd(b, a-b);
}

最小公倍數:\(\text{lcm}( a, b ) = a \div \gcd ( a, b ) \times b\). (先除后乘防爆 int. )

線性篩法

素數分布定理:對於不大於 \(n\) 的自然數集合, 素數個數 \(\pi(x)\sim\displaystyle\frac{n}{\ln{n}}\).

Euler 篩法(一種最常見的線性篩法):

基本思想:每個數只被最小的質因子篩一次, 即對於 \(a\) 是質數, \(b\) 的最小質因子不小於 \(a\) 的整數對 \(a, b\), 標記 \(ab\) 為合數實現:先枚舉 \(b\), 再枚舉 \(a\), 枚舉到 \(a|b\) 時結束.

int p[N/lnN]; // 素數分布定理
bool com[N];

for (int i=2; i<=n; i++) {
	if (!com[i]) p[++p[0]]=i;
	for (int j=1; j<=p[0] && i*p[j]<=n; j++) {
		com[i*p[j]]=true;
		if (i%p[j]==0) break;
	}
}

素因數分解(篩法優化):

int p[N/lnN], mfac[N];

for (int i=2; i<=n; i++) {
	if (!mfac[i]) p[++p[0]]=i;
	for (int j=1; j<=p[0] && i*p[j]<=n; j++) {
		mfac[i*p[j]]=p[j];
		if (i%p[j]==0) break;
	}
}

int fac[2 * sqrtN];  // 算術基本定理的推論
while (x > 1) {
    fac[++fac[0]] = mfac[x];
    x /= mfac[x];
}

數論函數

Bézout 定理:設 \(a, b\in \mathbf{Z}\), \((a, b) = d\), 存在 \(u,v\), 使得 \(ua+vb=d\).

算術基本定理(整數唯一分解定理):對於正整數 \(a\), 等式 \(a=p_1^{e_1} p_2^{e_2}\cdots p_n^{e_n}\) 唯一確定.

積性函數:對於 \((m,n)=1\), \(m,n∈\mathbf{N}^*\), 有 \(f(mn)=f(m)f(n)\). 要么 \(f(n)=0, \forall n\in \mathbf{N}^*\), 要么 \(f(1)=1\).

完全積性函數:對於一切 \(m, n\in\mathbf{N}^*\), 有 \(f(mn)=f(m)f(n)\).

Möbius 函數

\[\displaystyle \mu(n) = \begin{cases}1,\quad \ \ & n=1,\\ (-1)^k, \quad \ \ & n=p_1 p_2\cdots p_k,\\ 0,\quad \ \ & p^2 |n. \end{cases} \]

除數函數 \(\tau(n)\):正整數 \(n\) 的正因數個數.

\[\displaystyle\tau(n)=\sum_{d|n} 1 = \prod_{i=1}^k (e_i+1), \]

其中 \(n=p_1^{e_1} p_2^{e_2}\cdots p_k^{e_k}\) (唯一確定).

除數和函數:

\[\displaystyle\sigma(n)=\sum_{d|n} d=\prod_{i=1}^k \frac{1-p_i^{e_i+1}}{1-p_i}, \]

其中 \(n=p_1^{e_1} p_2^{e_2}\cdots p_k^{e_k}\) (唯一確定). 積性函數.

Euler 函數 \(\varphi(n)\):不超過正整數 \(n\) 的正整數 \(1,2,3,\ldots ,n-1\) 中與 \(n\) 互質的數的個數. 積性函數. \(\varphi(p)=p-1\).

\[\displaystyle\varphi(n)=n\prod_{i=1}^k (1-\frac{1}{p_i}). \]

void euler(int n) {
	for (int i=2; i<=n; ++i) phi[i]=i;
	for (int i=2; i<=n; ++i) if (phi[i]==i) 
		for (int j=i; j<=n; j+=i) phi[j]=phi[j]/i*(i-1);
}

取整函數

Gauss 函數 \([x]\):不大於 \(x\) 的最大整數. 又稱整數部分.

一般地, 地板函數 $ \lfloor x\rfloor=[x] $, 天花板函數 $ \displaystyle \lceil x\rceil=\begin{cases} [x], & x\in \mathbf{Z}, \\ [x]+1, & x\notin \mathbf{Z}\end{cases} $, 小數部分 $ \lbrace x\rbrace=x-[x] $.

常用性質:

\[[x]+[y]\le [x+y]\le [x]+[y]+1. \]

任取 $ x\in\mathbf{R} $, 都有 $ \displaystyle\left[x\right]+\left[x+\frac{1}{2}\right]=\left[2x\right] $.

\[[x]\cdot [y]\le [xy]. \]

\[\displaystyle\left[\frac{x}{n}\right]=\left[\frac{[x]+\{x\} }{n}\right] = \left[\frac{[x]}{n}+\frac{\{x\}}{n}\right]=\left[\frac{[x]}{n}\right]. \]

C++ 的默認取整方式為 向 0 取整。注意與取整函數的區別。

線性同余方程

拓展歐幾里得算法:

void exgcd(const int a, const int b, int &g, int &x, int &y) {
    if (!b) g=a, x=1, y=0;
    else exgcd(b, a%b, g, y, x), y -= x*(a/b);
}

若方程 \(ax+by=c\) (\(a,b,c\in\mathbf{Z}\)) 的一組整數解為 \((x_0,y_0)\), 則它的任意整數解可以寫成 \((x_0+kb',y_0-ka')\), 其中 \(\displaystyle a'=\frac{a}{\gcd(a,b)}\), \(\displaystyle b'=\frac{b}{\gcd(a,b)}\), \(\displaystyle k\in\mathbf{Z}\).

模線性方程組:

解方程 \(ax\equiv b\pmod n\): \(ax-b\) 即為 \(n\) 的倍數. 設 \(ax-b=ny\), 移項得 \(ax-ny=b\), 解線性同余方程即可.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM