快乐地打牢基础(6)——约数

约数定义: 若整数 n n n除以整数 d d d的余数为0,即 d d d能整除 n n n,则称 d d d n n n的约数, n n n d d d的倍数,记为 d   ∣   n d\ | \ n d  n

一、整除的性质


a , b a,b a,b是两个正整数,且 b ! = 0 b != 0 b!=0,则存在唯一的整数 q q q r r r,使得:
a = q b + r , ( 0 ≤ r < b ) a=qb+r,(0\leq r<b) a=qb+r0r<b
这个式子叫做带余除法,并记余数 r = a   m o d   b r = a\ mod\ b r=a mod b
整除具有如下性质:

  • a   ∣   b a\ |\ b a  b a   ∣   c a\ | \ c a  c,则 ∀ x , y , \forall x,y, x,y, a ∣ ( x b + y c ) {a|(xb+yc)} a(xb+yc)
  • a   ∣   b a\ |\ b a  b b   ∣   c b\ | \ c b  c,则 a   ∣   c a\ | \ c a  c
  • m   ! = 0 m \ != 0 m !=0,则当且仅当 m a ∣ m b ma|mb mamb时, a   ∣   b a\ |\ b a  b
  • a   ∣   b a\ |\ b a  b b   ∣   a b\ | \ a b  a a = ± b a=\pm b a=±b

二、约数


1.算术基本定理(唯一分解定理)的推论
在算术基本定理中,若正整数 N N N被唯一分解为 N = p 1 c 1 p 2 c 2 . . . p m c m N= p_{1}^{c_1} p_{2}^{c_2}... p_{m}^{c_m} N=p1c1p2c2...pmcm,其中 c i c_i ci都是正整数, p i p_i pi都是质数,且满足 p 1 < p 2 < . . . < p m p_1<p_2<...<p_m p1<p2<...<pm,则 N N N的正约数集合可写作:
{ p 1 b 1 p 2 b 2 . . . p m b m } , 其 中 0 ≤ b i ≤ c i \{p_1^{b_1}p_2^{b_2}...p_m^{b_m}\},其中0\leq b_i\leq c_i { p1b1p2b2...pmbm}0bici
N N N的正约数个数为( ∏ \prod 表示连乘)
( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ . . . ∗ ( c m + 1 ) = ∏ i = 1 m ( c i + 1 ) (c_1+1)*(c_2+1)*...*(c_m+1)=\displaystyle\prod^m_{i=1} (c_i+1) (c1+1)(c2+1)...(cm+1)=i=1m(ci+1)
N N N的所有正约数的和为
( 1 + p 1 + p 1 2 + . . . + p 1 c 1 ) ∗ ( 1 + p 2 + p 2 2 + . . . + p 2 c 2 ) ∗ . . . ∗ ( 1 + p m + p m 2 + . . . + p m c m ) = ∏ i = 1 m ( ∑ j = 0 c i ( p i ) j ) (1+ p_{1} +p_{1}^{2} +...+p_{1}^{c_1})*(1+ p_{2} +p_{2}^{2} +...+p_{2}^{c_2})*...*(1+ p_{m} +p_{m}^{2} +...+p_{m}^{c_m})=\displaystyle\prod^m_{i=1} (\displaystyle\sum^{c_i}_{j=0}(p_i)^j) (1+p1+p12+...+p1c1)(1+p2+p22+...+p2c2)...(1+pm+pm2+...+pmcm)=i=1m(j=0ci(pi)j)

//使用算术基本定理求质因子代码
//prime数组是之前用筛法筛出的质数数组。
void divide(ll n)
{
   
    int len = prime.size();
    int cnt = 0;
    for(int i = 0; i < len; i++)
    {
   
        if(n % prime[i] == 0)
        {
   
            p[++cnt] = prime[i];
            c[cnt] = 0;
            while(n % prime[i] == 0 && n > 1)
            {
   
                n /= prime[i];
                c[cnt]++;
            }
        }
        printf("p = %d c = %d\n",p[cnt],c[cnt]);
        if(n == 1)
            break;
    }
    //如果遍历到了1e6的素数,n还没有变为1,那么剩下的n一定是一个素数。(前提,n<1e12)
    if(n > 1){
   
        p[++cnt] = n,c[cnt] = 1;
    }
}
2.求N的正约数集合——试除法

d ≥ N d\geq \sqrt{N} dN N N N的约数,则 N / d ≤ N N/d\leq \sqrt{N} N/dN 也是 N N N的约数。换言之,约数总是成对出现的(除了对于完全平方数, N \sqrt{N} N 会单独出现)。
因此,只需要扫描 d = 1 ~ N d=1~\sqrt{N} d=1N ,尝试 d d d能否整除 N N N,若能整除,则 N / d N/d N/d也是 N N N的约数。时间复杂度 O ( N ) O(\sqrt{N}) O(N )

//试除法函数
int f[1600];
void divide(int n){
   
	m = 0;
	for(int i = 2; i * i <= n; i++){
   
		if(n % i == 0){
   
			f[++m] = i;
			if(i * i != n) f[++m] = n/i;
		}
	}	
	
}

试除法的推论
一个整数 N N N的约数个数的上界为 2 N 2\sqrt{N} 2N

3.求1~N每个数的正约数集合——倍数法

若用"试除法"分别求出 1 ~ N 1~N 1N每个数的正约数集合,时间复杂度过高,为 O ( N N ) O(N\sqrt{N}) O(NN )。可以反过来考虑,对于每个数 d d d 1 ~ N 1~N 1N中以 d d d为约数的数就是 d d d的倍数 d , 2 d , 3 d , . . . ⌊ N / d ⌋ ∗ d d,2d,3d,...\lfloor N/d\rfloor *d d,2d,3d,...N/dd。以下程序采用"倍数法"求出 1 ~ N 1~N 1N每个数的正约数集合:

//求1~N每个数的正约数集合——倍数法
vector<int> f2[500010];
void multiple(int n) {
   
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n/i; j++)
			f2[i*j].push_back(i);
}

倍数法的推论
1 ~ N 1~N 1N每个数的约数个数的总和大约为 N l o g N NlogN NlogN

【例题1】BZOJ 1053 反素数

题意:
如果一个大于等于 1 的正整数 n,满足所有小于 n 且大于等于 1 的所有正整数的约数个数都小于 n 的约数个数,则 n 是一个反素数。譬如:1,2,4,6,12,24,它们都是反素数。
现给定一个数 N ( 1 ≤ n ≤ 2 ∗ 1 0 9 ) N(1\leq n \leq2*10^9) N(1n2109),请你计算不大于 N的最大反素数。
思路:
g ( x ) g(x) g(x) x x x的约数个数。

  • 引理1: 1 ~ N 1~N 1N中最大的反素数就是,其中约数个数最多的数中最小的一个。

证明: m m m 1 ~ N 1~N 1N中约数个数最多的数中最小的一个。根据 m m m的定义, m m m显然满足: Ⅰ. ∀ x < m , g ( x ) < g ( m ) \forall x< m,g(x)<g(m) x<m,g(x)<g(m) Ⅱ. ∀ x > m , g ( x ) ≤ g ( m ) \forall x > m,g(x)\leq g(m)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值