[学习笔记]约数

(本篇并不适合初学者看)

1.定义:

若d能整除n,则d是n的约数,记为d|n

2.寻找

试除法:

约数成对出现(除了n是一个完全平方数)

根号n试除,能整除的就是一个约数。然后另一半也直接算上。

for(int i=1;i*i<=x;i++){
    if(n%i==0){
        factor[++tot]=i;
        if(i!=n/i) factor[++tot]=n/i;
    }
}

但是这样可能稍慢。

一个数的约数,从质因数分解的情况下来看,

n=p1^q1*p2^q2*....

根据乘法原理,约数个数就是:(q1+1)*(q2+1)*....

所以,可以直接质因数分解,

然后dfs搜出来所有因数。

这样,质因数分解的时候,可以

while(x%i==0)x/=i

这样,质因数分解上限是根号n,但不是严格根号n的。

然后dfs是约数个数复杂度的。

int yue[N],num;
int zhi[N],tot,cnt[N];
void dfs(int x,int now){
    if(x==tot+1){
        yue[++num]=now;
        return;
    }
    int tmp=1;
    for(int i=0;i<=cnt[x];i++){
        dfs(x+1,now*tmp);
        tmp*=zhi[x];
    }
}
void divi(int x){
    for(int i=2;(long long)i*i<=x;i++){
        if(x%i==0){
            zhi[++tot]=i;
            while(x%i==0){
                cnt[tot]++;
                x/=i;
            }
        }
    }
    if(x>1) zhi[++tot]=x,cnt[tot]=1;
}

试除法推论:一个数的约数个数上界是$2 imessqrt{n}$

 但是试除法好写啊。。

例题:[JSOI2009]瓶子和燃料

巧妙利用每个数约数,找到从n个数中选择k个数的最大公约数。

*1~N约数个数总和

考虑1~n的数能作为哪些数的约数

sum=n/1+n/2+n/3+...n/n=nlogn

3.筛法:从质因数分解方面考虑

筛法中转移只有两种情况:
pri[j]是i的最小质因子

pri[j]比i的最小质因子还小

①约数个数

设c[i]表示i最小质因子次数

f[i]表示i约数个数。

②约数和

$sum=(1+p_1+p_1^2+...+p_1^q1)*...*(1+p_k+p_k^2+...+p_k^qk)

设c[i]表示,i最小质因子的贡献。即:(1+p_1+p_1^2+...+p_1^q1)(假设p1是最小质因子)

设f[i]表示i约数和。

具体转移见:

SIEVE 线性筛

4.最大公约数gcd

前置:裴属定理:

若gcd(a,b)=1,则存在x,y,使得x*a+y*b=1

所以也存在x,y, 使得x*a+y*b=gcd(a,b)

扩展一下:

整数a1,a2,...,an

存在x1,x2,..xn使得,x1*a1+x2*a2+..+xn*an=gcd(a1,a2...,an)

求法:

①辗转相减法,高精gcd

直接无脑减肯定太慢。

A,B

如果A为偶数,B为奇数,先把A除以2除成奇数。因为肯定没有2这个因子了。

同理,如果B为偶数,A为奇数,也这样。

如果A,B同为偶数,把2不断提出来,乘进gcd,直到一个变成奇数。

如果A,B同为奇数,直接gcd(A,B)=gcd(A,A-B)其中,A>=B

奇数相减一定出偶数,还可以再/2

这样,平均的复杂度也是log级别的。

②欧几里得算法

gcd(a,b)=gcd(b,a%b)

证明:对于d|a,d|b,d|gcd(a,b)

设b=q*a+r, r=a%b

所以,d|q*b,

所以,d|(a-q*b)=r

所以,对于a,b所有的公约数,也是r的约数,所以,最大公约数也一定是b,r的最大公约数。

③扩展欧几里得算法exgcd

裴属定理告诉我们,x*a+y*b=gcd(a,b)有解

可以计算x*a+y*b=gcd(a,b)

x,y的一组解和通解。

EXGCD 扩展欧几里得

(最小公倍数)

④一些性质:

  1.gcd(Fibo[n],Fibo[m])=Fibo[gcd(n,m)]

  2.gcd(a1,a2,...,an)=1 等价于:

  $sum_{d|ai}space mu(d) =1

  如果答案不是1,gcd就不是1,就不互质。

  证明:

  对于两个数i,j

  i,j互质的时候,公约数只有1,u(1)=1

  i,j不互质的时候,公约数就是i,j最大公约数的约数。

  设gcd(i,j)=p1^q1*p2^q2*...pk^qk

  那么,如果取两个以上的pi,u就是0,不影响答案。

  所以,就是取p1、。。。pk一个或不取的方案数要考虑

  取零个:C(k,0)个1

  取一个 :C(k,1)个-1

  取两个 :C(k,2)个1

  。。。

  所以,最后的答案是:C(k,0)-C(k,1)+C(k,2)-C(k,3)+...+C(k,k)

  根据组合数的性质,不论k是奇数还是偶数,答案都是0

  证毕。

  

最大公约数与最小公倍数——质因数分解考虑法。

例题:Hankson的趣味题

5.互质与欧拉函数。

①定义:phi(i)表示,1~i中和i互质的数的个数。

公式:phi(i)=n*(1-1/p1)*(1-1/p2)...(1-1/pk)p是质因子。

可以容斥原理证明:n-n/p1-n/p2+n/(p1*p2)。。。

②欧拉函数性质

1.任意的n>1,1~n中和n互质的数的总和为$n*phi(n)/2$

证明:
因为gcd(n,x)=gcd(n,n-x)所以,如果x和n互质,那么n-x也和n互质

互质的数成对出现(即$phi(i)$都是偶数,除了$phi(2)$)。平均值是n/2,所以总和是$n*phi(n)/2$

2.若a,b互质,则$phi(ab)=phi(a) imes phi(b)$

根据公式,质因数分解,两边的质因子都是互不相同的,恰好可以拼成ab欧拉函数的值。

3.$sum_{d|n} space phi(d) = n$

证明:

(网上证明有很多,这里说一下我的伪证明)

我的感觉是,好像把所有的约数的phi加在一起就是n的话,

也就是说,与约数d互质的所有数,应该能乘上一个数,一起覆盖完1~n

对于所有属于1~n的一个数x,设gcd(n,x)=g

那么,n/g与x/g一定互质。

那么,与n的gcd都为g的所有的x,其个数就是$phi(n/g)$

对于一个x,其和n的gcd唯一。

而对于n的一个约数d,n/d也是唯一的,

这里,gcd和n/d其实就是相同的。

那么,我们可以找对于所有的n的约数g,

与n的最大公约数为g的数,可以唯一对应一些x

那么,我们枚举所有的约数g,就对应完了所有的x也就是1~n

而n/g也是n的一个约数,

所以可以说,$sum_{d|n} space phi(d) = n$

③欧拉函数寻找:根据定义即可。

也是直接的试除法根号n分解。

int phi(int n){
    int ret=n;
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            ret=ret/i*(i-1);
            while(n%i==0) n/=i;
        }
    } 
    if(n>1) ret=ret/n*(n-1);
    return ret;
}

④欧拉函数筛法

把定义稍微变一下形,

phi(i)=n*(1-1/p1)*(1-1/p2)...(1-1/pk)

如果我们把n质因数分解,那么其实就是:

$(p_1^q1-p_1^{q1-1})*....*(p_k^qk-p_k^{qk-1})$

所以现在,

直接通过定义筛即可。

如果pri[j]和i互质,那么$phi(i*pri[j])=phi(pri[j]) imes phi(i)$积性函数的性质。

如果pri[j]和i不互质,那么$phi(i*pri[j])=phi(i) imes pri[j]$次数多了一个1

例题:仪仗队

总结:

约数的考察主要对于gcd,和互质的欧拉函数。

约数的很多性质都可以用质因数分解表示和解释。

对于后面的同余,有着奠基的意义。

原文地址:https://www.cnblogs.com/Miracevin/p/9708090.html