簡單數學



突然發現之前也寫過一篇文章叫“簡單數學”,緣,妙不可言


博主整理了一下\(OI\)中簡單的數論知識,故取名簡單數學,以后會隨着學習的深入慢慢擴展開來。

以下的代碼部分沒經過驗證,可能一定會出鍋

質數

質數的判定

顧名思義就是判定某一個數是不是質數

試除法

一個結論:

若一個正整數\(N\)為合數,那么一定存在一個正整數\(T\)能夠整除\(N\),且\(2\le N \le \sqrt N\)

該結論可以通過反證法證明,這里不再贅述(直接背過他不香嗎?)

bool judge_prime(int N){
    for(int i=2;i*i<=N;++i)
        if(N%i==0) return 0;
    return 1;
}

容易看出復雜度為\(O( \sqrt N)\)

質數的篩選

顧名思義就是曬出出\(1\backsim N\)中的質數

Eratosthenes篩法

核心思想就是質數的倍數是合數,具體不再贅述

void primes(int n){
    memset(v,0,sizeof(v));
    for(int i=2;i<=n;++i)
    {
        if(v[i]) continue;
        prime[++cnt]=i;//i是質數
        for(int j=i*2;j<=n;j+=i) v[j]=1;
	}
}

復雜度為\(O(\sum_{質數p\le \frac{N}{p}})=O(N\ \log \log N)\)

線性篩法

核心思想就是通過“從小到大積累質因子”的方式來標記合數,以此來避免\(Eratosthenes\)篩法重復標記合數的問題

具體實現原理簡單來說就是:每個合數\(i*p\)只會被它的最小質因子篩一次

void primes(int n){
    memset(v,0,sizeof(v));//最小質因子
    cnt=0;//質數的數量
    for(int i=2;i<=n;++i)
    {
        if(v[i]==0) {prime[++cnt]=i;v[i]=i;}
        for(int j=1;j<=cnt;++j)
        {
            if(prime[j]>v[i]||prime[j]>n/i) break;
            v[i*prime[j]]=prime[j];
        }
    }
}
//於2020.7.6更正代碼

復雜度為\(O(N)\)我一般都是用埃氏篩

算術基本定理

任何一個大於\(1\)的正整數都能被唯一分解為有限個質數的乘積的形式,寫作:

\[N=p_1^{c_1}p_2^{c_2}...p_m^{c_m} \]

其中\(c_i\in\N^+\),\(p_i\)都是質數,且滿足\(p_1<p_2<...<p_m\)

試除法分解質因數

就是結合一下埃氏篩和試除法

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

復雜度為\(O( \sqrt N )\)

約數

算術基本定理的推論

如果一個正整數被分解成了\(N=p_1^{c_1}p_2^{c_2}...p_m^{c_m}\)這種形式,則\(N\)的正約數集合可以寫作

\(p_1^{b_1}p_2^{b_2}...p_m^{b_m}\)其中\(0\le b_i \le c_i\)

約數個數

\(N\)的正約數個數為\(\prod\limits_{i=1}^m(c_i+1)\)

約數和

\(N\)的所有正約數和為\(\prod\limits_{i=1}^m(\sum\limits_{j=0}^{c_i}(p_i)^j)\)

\(N\)的正約數集合

試除法

核心就是利用約數總是成對出現(除了對於完全平方數,\(\sqrt{N}\)會單獨出現)

for(int i=1;i*i<=N;++i)
{
    if(n%i==0)
    {
        d[++cnt]=i;
        if(i!=n/i) d[++cnt]=n/i;
	}
}

復雜度為\(O( \sqrt N)\)

試除法的推論

一個正整數的約數個數上界為\(2 \sqrt N\)

倍數法

\(1\backsim N\)中每個數的正約數集合

核心思路就是對於每個約數\(d\),以它為約數的正整數為\(d,2d,3d...\left\lfloor\dfrac{N}{d}\right\rfloor*d\)

for(int i=1;i<=n;++i)
	for(int j=1;j<=n/i;++j)
        f[i*j].push_back(i);

復雜度為\(O(N+\frac{N}{2}+\frac{N}{3}...+\frac{N}{N})=O(N\log N)\)

倍數法推論

\(1\backsim N\)中每個數的約數個數的總和大約為\(N \log N\)

最大公約數

定理

\(\forall a,b\in \N \ \ \ \gcd(a,b)*lcm(a,b)=a*b\)

更相減損法

\(\forall a,b\in \N,a\ge b \ \ \ \ \gcd(a,b)=\gcd(b,a-b)=\gcd(a,a-b)\)

\(\forall a,b\in \N \ \ \ \gcd(2a,2b)=\gcd(a,b)\)

如果需要高精度計算時,高精度除法(取模)很惡心人,可以用更相減損法來替代歐幾里得算法

歐幾里得法

\(\forall a,b\in \N \ \ \ \gcd(a,b)=\gcd(b,a\%b)\)

int gcd(int a,int b)
{
    if(!b) return a;
    return gcd(b,a%b)
}

互質與歐拉函數

歐拉函數

定義

\(1\backsim N\)中與\(N\)互質的數的個數,記為\(\varphi(N)\)

$\varphi(N)=N*\prod\limits_{質數p|N}(1-\frac{1}{p}) $

於2020.11.6修改錯誤/kk

積性函數

如果\(a,b\)互質時,有\(f(ab)=f(a)*f(b)\),那么函數\(f\)就是積性函數

積性函數的性質

\(f\)是積性函數,且在算術基本定理中\(n=\prod_{i=1}^mp_i^{c_i}\)\(f(n)=\prod_{i=1}^{m}f(p_i^{c_i})\)

歐拉函數基本性質
  1. \(\forall\ n>1,1\backsim n\)中與\(n\)互質的數的和為\(n*\varphi(n)/2\)
  2. \(a,b\)互質,則\(\varphi(ab)=\varphi(a)*\varphi(b)\)(積性函數的性質)
  3. \(p\)是質數,若\(p\mid n\)\(p^2\mid n\),則\(\varphi(n)=\varphi(n/p)*p\)
  4. \(p\)是質數,若\(p\mid n\)但是\(p^2 \nmid n\)\(\varphi(n)=\varphi(n/p)*(p-1)\)
  5. \(\sum_{d\mid n}\varphi(d)=n\)
試除法求歐拉函數

根據歐拉函數的計算計算式,可以在分解質因數時順便求出歐拉函數

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;
}

復雜度為\(O(\sqrt N)\)

\(Eratosthenes\)篩法求歐拉函數

根據歐拉函數的計算式,可以在\(O(n \log n)\)的時間內求出\(2 \backsim n\)中每個數的歐拉函數

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[j]=phi[j]/i*(i-1);
            
}
線性篩快速遞推歐拉函數
  1. \(p\)是質數,若\(p\mid n\)\(p^2\mid n\),則\(\varphi(n)=\varphi(n/p)*p\)
  2. \(p\)是質數,若\(p\mid n\)但是\(p^2 \nmid n\)\(\varphi(n)=\varphi(n/p)*(p-1)\)

利用上述性質,在線性篩每個合數\(n\)被最小質因子\(p\)篩掉的時候通過\(\varphi(n/p)\)遞推到\(\varphi(n)\)

代碼就不寫了,我沒寫過這種方法(我菜)

同余

同余,同余類和剩余系的定義

自己百度吧,懶得寫了\(qwq\)

費馬小定理

\(p\)為質數,則對於任意整數\(a\),都有\(a^p \equiv a (\mod p)\)

歐拉定理

若正整數\(a,n\)互質,則\(a^{\varphi(n)} \equiv 1(\mod n)\)

歐拉定理的推論

若正整數\(a,n\)互質,則\(a^n \equiv a^{n\% \varphi(n)}(\mod n)\)

若正整數\(a,n\)不一定互質時,且\(b> \varphi (n)\)\(a^b \equiv a^{b\%\varphi(n)+\varphi(n)}(\mod n)\)

可用於歐拉降冪

裴蜀定理

對於任意整數\(a,b\),都存在一對整數\(x,y\),滿足\(ax+by=\gcd(a,b)\)

擴展歐幾里得算法

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

注意

上述程序求出方程\(ax+by=\gcd(a,b)\)的一組特解\(x_0,y_0\)

對於更為一般的方程\(ax+by=c\)而言,當\(d\mid c\)時方程有解,此時方程的解為\((c/d)*x_0,(c/d)*y_0\)

方程\(ax+by=c\)的通解可以表示為:

\(x=\frac{c}{d}x_0+k\frac{b}{d}\)

\(y=\frac{c}{d}y_0-k\frac{a}{d}\)

通過上式就可以求出最小正整數解了,\(qwq\)

乘法逆元的計算和應用

大概就是一個整數,能讓\(a/b\)在模\(p\)的意義下等於\(a*inv(b)\)

然后就可以到處取模了,\(qwq\)

逆元的計算
根據費馬小定理求解

對於\(a/b(\mod p)\)而言

\(p\)為質數,則根據費馬小定理,\(b^{p-1} \equiv 1(\mod p)\)

\(b*b^{p-2}\equiv 1(\mod p)\)

\(b^{p-2}\)即為\(b\)的乘法逆元

求解同余方程

如果只保證\(b,p\)互質,則可以通過直接求解同余方程\(b*x\equiv 1(\mod p)\)

線性遞推逆元
利用階乘遞推逆元

由於\(a=\frac{a!}{(a-1)!}\)

\(a^{-1}\equiv(a-1)!a!^{-1}\)

\((a-1)!\equiv a!^{-1}a\)

可以求出\(1...k\)的階乘,然后利用快速冪求出\(k!\)的逆元,然后反推\(1...k\)的階乘的逆元

該方法也可以求出任意\(k\)個數的階乘,即把階乘換成前綴和


\[未完待續 \]



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM