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

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

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

质数

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

互质数:两个或多个整数的公因数只有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 n都可以表达为如下形式:

n = p 1 a 1 × p 2 a 2 × . . . × p k a k n=p_1^{a_1}\times p_2^{a_2}\times ...\times p_k^{a_k} n=p1a1×p2a2×...×pkak,其中, ∀ i ∈ [ 1 , k ] , p i \forall i\in [1,k], p_i i[1,k],pi为质数

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

α = p 1 b 1 × p 2 b 2 × . . . × p k b k \alpha=p_1^{b_1}\times p_2^{b_2}\times ...\times p_k^{b_k} α=p1b1×p2b2×...×pkbk,其中, ∀ i ∈ [ 1 , k ] \forall i\in [1,k] i[1,k] 0 ≤ b i ≤ a k 0\leq b_i \leq a_k 0biak

那么对于每一个 b i b_i bi,都有 ( a i + 1 ) (a_i+1) (ai+1)种取法,因此, n n n的所有约数之和为 ( a 1 + 1 ) ( a 2 + 1 ) . . . ( a k + 1 ) (a_1+1)(a_2+1)...(a_k+1) (a1+1)(a2+1)...(ak+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. 约数之和

∑ α 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 ) \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}) αi=(p10+p11+...+p1a1)(p20+p21+...+p2a2)...(pk0+pk1+...+pkak)

展开该式子,就可以得到 α = p 1 b 1 × p 2 b 2 × . . . × p k b k \alpha=p_1^{b_1}\times p_2^{b_2}\times ...\times p_k^{b_k} α=p1b1×p2b2×...×pkbk,所有的 b i b_i bi取值的组合相加。实际上,这个式子展开一共有 ( a 1 + 1 ) ( a 2 + 1 ) . . ( a k + 1 ) (a_1+1)(a_2+1)..(a_k+1) (a1+1)(a2+1)..(ak+1)项,也对应了约数个数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值