[数学基础] 1 杂七杂八小知识

这里放了一些我觉得在学习各种筛和数论定理之前,应该了解的小知识,可以对数论有一个初步的印象。包括了:

  1. 质数的概念,约数的概念,以及一个非常重要又简单的定理:整数唯一分解。我们应该会在后面见到它很多次。
  2. 解题的时候,或者写暴力的时候,我们也经常的需要求约数的各种性质,因此这里列的代码还是蛮实用的。

质数

  • 定义:大于1,且除了1和它本身之外不再有其他因数的自然数。
  • 质数分布定理:\(1\)~\(n\)间的质数大概有\(\pi(n)=\frac{n}{\ln n}\)

互质数:两个或多个整数的公因数只有1的非0自然数。

  • 小性质:最小的9个质数相乘,答案在int范围内。

约数

1. 试除法求约数

(1) 求所有的质因数
void div(int x){
	for (int i=2;(ll)i*i<=x;++i){
		int cnt = 0;
		while (x%i==0){
			x /= i; cnt++;
		}
		if (cnt) printf("%d %d\n", i, cnt);
	}
	if (x > 1) printf("%d %d", x, 1);
	puts("");
}
(2) 求所有的约数

使用筛法先筛质数,再通过dfs枚举约数

int n, cnt, tot, dn;
const int N = 5e4 + 5;
bool st[N];
int p[N], d[N];
pii f[N];

void dfs(int u, int x){
	if (u > tot){
		d[++dn] = x; return ;
	}
	for (int i=0;i<=f[u].yy;++i){
		dfs(u + 1, x);
		x *= f[u].xx;
	}
}

void solve(){
	int a0, a1, b0, b1;
	scanf("%d%d%d%d", &a0, &a1, &b0, &b1);
	int n = b1;
	tot = 0;
	for (int i=1;p[i]<=n/p[i];++i){
		if (n % p[i] != 0) continue;
		int sm = 0;
		while (n % p[i] == 0) n /= p[i], ++sm;
		f[++tot] = pii(p[i], sm);
	}
	if (n > 1) f[++tot] = pii(n, 1);
	dn = 0;
	dfs(1, 1);
}

2. 约数个数

任何一个正整数\(n\)都可以表达为如下形式:

\(n=p_1^{a_1}\times p_2^{a_2}\times ...\times p_k^{a_k}\),其中,\(\forall i\in [1,k], p_i\)为质数

那么,对于\(n\)的任意约数\(\alpha\),都可以将\(\alpha\)写成如下形式:

\(\alpha=p_1^{b_1}\times p_2^{b_2}\times ...\times p_k^{b_k}\),其中,\(\forall i\in [1,k]\)\(0\leq b_i \leq a_k\)

那么对于每一个\(b_i\),都有\((a_i+1)\)种取法,因此,\(n\)的所有约数之和为\((a_1+1)(a_2+1)...(a_k+1)\)

  • 小性质:所有int范围内的数,约数之和最多的约为1500

小例子:求n!的约数之和

int n, cnt;
const int N = 1e6 + 5;
int p[N], num[N];
bool st[N];

void Euler(int n){
    for (int i=2;i<=n;++i){
        if (!st[i]) p[++cnt] = i;
        for (int j=1;p[j]<=n/i;++j){
            st[p[j] * i] = true;
            if (i % p[j] == 0) break;
        }
    }
}

int main(void){
    scanf("%d", &n);
    Euler(N - 1);
    for (int i=2;i<=n;++i){
        if (st[i]) continue;
        for (ll j = i;j<=n;j*=i){
            num[i] += n / j;
        }
    }
    for (int i=2;i<=n;++i){
        if (num[i]){
            printf("%d %d\n", i, num[i]);
        }
    }

    return 0;
}

3. 约数之和

\(\sum \alpha_i=(p_1^0+ p_1^1+ ...+ p_1^{a_1})(p_2^0+ p_2^1+ ...+ p_2^{a_2})...(p_k^0+ p_k^1+ ...+ p_k^{a_k})\)

展开该式子,就可以得到\(\alpha=p_1^{b_1}\times p_2^{b_2}\times ...\times p_k^{b_k}\),所有的\(b_i\)取值的组合相加。实际上,这个式子展开一共有\((a_1+1)(a_2+1)..(a_k+1)\)项,也对应了约数个数。

posted @ 2022-05-09 23:43  跳岩  阅读(223)  评论(1)    收藏  举报