从普及到提高的一些数论知识
???? 写在前面

没有证明,实际的证明在做题的时候也没多大用,(证明看一遍忘一遍)别记错模版和复杂度就行。
\(\\\)
\(\\\)
\(\\\)

????质数与合数

对于一个正整数\(N\),不超过它的质数有\(\frac{N}{lnN}\)个。
\(\\\)

质数的判定

试除法\(O(\sqrt n)\)

结论:若一个正整数\(N\)为合数,那么一定存在一个能够整除\(N\)的正整数\(T\),使得\(2\le T\le \sqrt n\)

bool is_prime(int n){
    if(n<2) return false;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i==0) return false;
    return true;
}

\(\\\)

质数的筛选

埃式筛法\(O(NloglogN)\)

结论:任意整数\(x\)的倍数\(2x,3x,…\)都不是质数。

void primes(int n){
    for(int i=2;i<=n;i++){
        if(v[i]) continue;
        prime[++cnt]=i;//不是2~i-1任何一个数的倍数
        for(int j=i;j<=n/i;j++){//从i的i倍开始,小于i倍的已经被标记过了
            v[i*j]=true;
        }
    }
}

线性筛法\(O(N)\)

记录mindiv,让每个数只被它的最小质因数筛一次。

void primes(int n){
    memset(mindiv,0,sizeof(mindiv));
    cnt=0;
    for(int i=2;i<=n;i++){
        if(mindiv[i]==0){
            mindiv[i]=i;
            prime[++cnt]=i;
        }
        for(int j=1;j<=cnt;j++){
            if(prime[j]>mindiv[i]||i*prime[j]>n) break;
            mindiv[i*prime[j]]=prime[j];
        }
    }
}

\(\\\)

质因数分解

算数基本定理(唯一分解定理)

任何一个大于\(1\)的正整数都能唯一分解为有限个质数的乘积。即:

\(N=p_1^{c_1}p_2^{c_2}p_3^{c_3}…p_m^{c_m}\)

试除法\(O(\sqrt n)\)

做法:扫描\(2\)~\(\sqrt n\)里的每个数\(d\),若\(d|n\),那么删掉\(n\)中的所有因子\(d\),并累计个数。

正确性:一个合数的因子一定在扫到合数之前就被删除了,所以能整除\(n\)的一定是小于n的质数。

void divide(int n){
    cnt=0;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0){
            p[++cnt]=i;
            while(n%i==0) n/=i,c[cnt]++;
        }
    }
    if(n>1){
        p[++cnt]=n;
        c[cnt]=1;
    }
}

\(\\\)
\(\\\)
\(\\\)

???? 约数与倍数

唯一分解定理的推论

\(n\)的正约数个数为:\((c_1+1)\times (c_2+1)\times …\times(c_m+1)\)

\(n\)的正约数和为:\((1+p_1+{p_1}^2+…+p_1^{c_1})\times …\times (1+p_m+{p_m}^2+…+{p_m}^{c_m})\)
\(\\\)

约数的求解

\(n\)的正约数集合—试除法\(O(\sqrt n)\)

结论:若\(d\)\(n\)的约数,那么\(n/d\)也是\(n\)的约数。

推论:一个整数\(n\)约数个数上界是\(2\sqrt n\)

void get_factor(int n){
    for(int i=1;i<=sqrt(n);i++){
        if(n%i==0){
            factor[++cnt]=i;
            if(i!=n/i) factor[++cnt]=n/i;
        }
    }
}

\(1\)~\(n\)的正约数集合—倍数法

推论:\(1\)~\(n\)的约数个数上届是\(nlogn\)

void get_factor(int n){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n/i;j++)
            factor[i*j].push_back(i);
    }
}

\(\\\)

最大公约数与最小公倍数

结论:\(\text{lcm}(a,b)=\frac{a\times b}{\text{gcd}(a,b)}\)

欧几里得算法\(O(log\ {a+b})\)

int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}

\(\\\)
\(\\\)
\(\\\)

????欧拉函数 欧拉函数的性质
  • \(\forall n>1,1\)~\(n\)中与\(n\)互质的数的和为\(\frac{n\times \varphi(n)}{2}\)
  • \(a,b\)互质,则\(\varphi(a\times b)=\varphi(a)\times \varphi(b)\)
  • \(p\)为质数,\(p|n\)\(p^2|n\),则\(\varphi(n)=\varphi(n/p)\times p\)
  • \(p\)为质数,\(p|n\)\(p^2\nmid n\),则\(\varphi(n)=\varphi(n/p)\times p\)
  • \(\sum_{d|n}\varphi(d)=n\)
    \(\\\)
欧拉函数的求解

求解\(n\)的欧拉函数\(O(\sqrt n)\)

结论:在算数基本定理中,\(N={p_1}^{c_1}{p_2}^{c_2}…{p_m}^{c_m}\),那么\(\varphi(N)=N*\frac{p_1-1}{p_1}*\frac{p_2-1}{p-2}*…*\frac{p_m-1}{p_m}\)

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

求解\(1\)~\(n\)的欧拉函数

埃式筛法\(O(nlogn)\)

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[i*j]=phi[j]/i*(i-1);
        }
    }
}

线性筛法\(O(n)\)

void euler(int n){
    memset(mindiv,0,sizeof(mindiv));
    cnt=0;
    for(int i=2;i<=n;i++){
        if(mindiv[i]==0){
            mindiv[i]=i;prime[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=cnt;j++){
            if((prime[j]>mindiv[i])||(prime[j]>n/i)) break;
            mindiv[i*prime[j]]=prime[j];
            phi[i*prime[j]]=phi[i]*(i%prime[j]?(prime[j]-1):prime[j]);
        }
    }
}

\(\\\)
\(\\\)
\(\\\)

???? 同余

费马小定理

\(p\)是质数,则对于任意整数\(a\),有\(a^p\equiv a (\text{mod} \ p)\)
\(\\\)

欧拉定理

\(gcd(a,n)=1\),那么\(a^{\varphi(n)}\equiv 1(\text{mod} \ n)\)
\(\\\)

扩展欧拉定理

\[a^b\equiv\begin{cases} a^{b\ \text{mod}\ \varphi(n)}(\text{if}\ \text{gcd} (a,b)=1)\\ a^{b\ \text{mod}\ \varphi(n)+\varphi(n)}(\text{if}\ \text{gcd} (a,b)\not=1,b\ge \varphi(n))\\ a^b(\text{if}\ \text{gcd} (a,b)\not=1,b <\varphi(n)) \end{cases}(\text{mod}\ n) \]

\(\\\)

裴蜀定理

对于任意整数\(a,b\),存在一对整数\(x,y\),使得\(ax+by=\text{gcd}(a,b)\)

我的理解是,如果存在一个数\(c\),使得\(ax+by=c\)成立,那么\(c\)一定能整除\(\text{gcd}(a,b)\)
\(\\\)

扩展欧几里得算法\(O(log\ {a+b})\)

用来求\(ax+by=\text{gcd}(a,b)\)的一组可行解\(x_0\),\(y_0\)

void exgcd(int a,int b,int &x,int &y){
    if(b==0) {x=1;y=0;return a;}
    int gcd=exgcd(b,a%b,x,y);
    int tmp=x;x=y;y=tmp-(a/b)*y;
    return gcd
}

对于一般方程\(ax+by=c\)

  • 有解条件:\(gcd\mid c\)
  • 可行解:\(x=\frac{c}{gcd}x_0\),\(y=\frac{c}{gcd}y_0\)
  • 通解:\(x=\frac{c}{gcd}x_0+k\frac{b}{gcd}\),\(y=\frac{c}{gcd}y_0-k\frac{a}{gcd}(k\epsilon\mathbb{Z} )\)
    \(\\\)
    \(\\\)
    \(\\\)
????乘法逆元

求解\(a\)在模\(n\)意义下的逆元\(a^{-1}\)

快速幂法\(O(log_2n)\)

适用条件:\(n\)为质数

int qpow(int a,int b,int n){
    int res=1;
    while(b){
        if(b&1) res=res*a%n;
        a=a*a%n;
        b>>=1;
    }
    return res;
}
qpow(a,n-2,n);

扩展欧几里得法\(O(log_2{a+n})\)

转化为\(a*x\equiv1(\text{mod}\ n)\Rightarrow\ a*x+n*y=1\),求出一组特解\(x_0,y_0\)\(x_0\)就是一个\(a\)在模\(n\)意义下的逆元。

适用条件:\(gcd(a,n)=1\)

通解:\(x\equiv x_0(\text{mod} n)\)

最小整数解:\((x_0+n)\%n\)

void exgcd(int a,int b,int &x,int &y){
    if(b==0) {x=1;y=0;return a;}
    int gcd=exgcd(b,a%b,x,y);
    int tmp=x;x=y;y=tmp-(a/b)*y;
    return gcd
}
exgcd(a,n,x,y)

求解\(1\)~\(n\)中,每个数在模\(p\)意义下的逆元\(O(n+log(p))\)

适用条件:\(p\)为质数

void getinv(){
    s[0]=1;
    for(int i=1;i<=n;i++) s[i]=s[i-1]*a[i]%p;
    sv[n]=qpow(s[n],p-2,p);
    for(int i=n;i>=1;i--) sv[i-1]=sv[i]*a[i]%p;
    for(int i=1;i<=n;i++) inv[i]=sv[i]*s[i-1]%p;
}

\(\\\)
\(\\\)
\(\\\)

???? 同余方程

求解同余方程

给定整数\(a,b,m\),求解一个整数\(x\)满足\(a*x\equiv b(\text{mod}\ m)\),或者判定无解

\(a*x\equiv b(\text{mod}\ m)\Rightarrow a*x+m*y=b\)

判定有解:\(\text{gcd}(a,m)|b\)

通解:\(x_0*\frac{b}{\text{gcd}(a,m)}+k*\frac{m}{\text{gcd}(a,m)}\)
\(\\\)

中国剩余定理

对于如下的方程组

\(\begin{cases} x\equiv a_1\ (\text{mod}\ m_1)\\ x\equiv a_2\ (\text{mod}\ m_2)\\ \vdots \\ x\equiv a_n\ (\text{mod}\ m_n)\\ \end{cases}\)

求解\(x\),其中\(m\)两两互质。

\(m=\prod_{i=1}^n m_i\)\(M_i=\frac{m}{m_i}\)\(t_i\)是同余方程\(M_it_i\equiv1(\text{mod}\ m_i)\)的一个解。

可行解:\(x_0=\sum_{i=1}^{n}a_iM_it_i\)

通解:\(x=x_0+km\)

最小正整数解:\(x=(x_0+m)\%m\)

int crt(int k,int *a,int *b){
    int m=1,ans=0;
    for(int i=1;i<=k;i++) m=m*b[i];
    for(int i=1;i<=k;i++){
        int M=m/b[i],t,y;
        exgcd(M,b[i],t,y);
        ans=((ans+a[i]*M*t%m)+m)%m;
    }
    return (ans+m)%m;
}

\(\\\)

威尔逊定理(www)

我刚知道考纲里还有这个????