【數學】NOIP數論內容整理


NOIP數論內容整理

注:特別感謝sdsy的zxy神仙以及lcez的tsr筮安幫助審稿

一、整除:

對於\(a,b~\in~Z\),若\(\exists~k~\in~Z\),\(s.t.~b~=~k~\times~a\),則說\(a\)整除\(b\),記做\(a~|~b\)

二、帶余除法:

\(~\forall~a,b~\in~z\)存在且僅存在唯一的\(q,r~\in~Z^*\)\(s.t.~b~=~q~\times~a+r\),其中\(r~\in~[0,a)\)。記做\(r~=~b~Mod~a\)

三、公約數

\(a,b~\in~Z\),若\(~\exists~k,x,y~\in~Z^*\)\(s.t.~a~=k~\times~x,b~=~k~\times~y\),則說\(k\)\(a,b\)的公約數。公倍數同理。

四、\(gcd\)\(lcm\)

\(a,b\)的最大公約數為\(gcd(a,b)\),最小公倍數為\(lcm(a,b)\)

五、最大公約數與最小公倍數乘積性質定理

性質:\(a~\times~b=gcd(a,b)~\times~lcm(a,b)\)

六:最大公約數的求取:(以下不妨設\(b~\leq~a\))

更相減損術:\(gcd(a,b)~=~gcd(b,a-b)\)

歐幾里得算法:\(gcd(a,b)~=~gcd(b,a~Mod~b)\)

其中,更相減損術的復雜度是\(O(n)\),歐幾里得算法的復雜度是\(O(logn)\)。其中\(n~=~\max(a,b)\)

七:更相減損術的優化

引理:\(\forall~m~\neq~0,~a,b~\in~Z\),有\(m~\times~gcd(a,b)=gcd(ma,mb)\)

\(a,b\)是兩個偶數時,顯然\(gcd(a,b)\)有一因數\(2\)。於是\(gcd(a,b)~=~2~\times~gcd(\frac{a}{2},\frac{b}{2})\)

\(a,b\)一奇一偶的時候,不妨設\(a\)是偶數。顯然\(gcd(a,b)\)不含因子\(2\)。於是有\(gcd(a,b)=gcd(\frac{a}{2},b)\)

\(a,b\)同為奇數時,直接應用更相減損術。\(gcd(a,b)=gcd(b,a-b)\)

考慮兩個奇數相減答案顯然是偶數。於是一次更相減損術顯然對應一個數除以2的操作。即更相減損的次數與除以二的操作次數同階。考慮一個數最多被除\(log\)次。於是該算法的復雜度為\(O(logn)\)

該算法常用在對兩個高精度數求\(gcd\),因為兩個高精度數做除法的復雜度難以承受,從而應用該算法。

八、例題:

給定一個序列,要求支持區間加法。多次查詢區間內所有數字的\(gcd\)\(n,m,a_i~\leq~10^5\)

Solution:

因為區間加法無法維護\(gcd\),所以顯然不能暴力線段樹。考慮對原序列做差分。由更相減損定理,顯然成立\(gcd(a,b,c)~=~gcd(a,b-a,c-b)\)。於是差分后區間加法改為單點修改操作。於是一次操作的復雜度為\(O(log^2n)\)。總時間復雜度為\(O\left(m\log^2n\right)\),可以通過本題。

九、擴展歐幾里得算法

裴蜀定理:關於\(x,y\)的方程\(ax+by=c\)有解當且僅當\(gcd(a,b)|c\)

求關於\(x,y\)的方程\(ax+by=c\)的一組整數解。

不妨設\(c=gcd(a,b)\)。否則左側乘一常數\(k\),不失一般性

根據歐幾里得算法,有

\[gcd(a,b)=gcd(b,a~Mod~b) \]

於是有

\[ax+by=gcd(a,b)=gcd(b,a~Mod~b)=bx_0+(a~Mod~b)y_0 \]

於是有

\[\begin{align} ax+by & = bx_0+(a-\left\lfloor\frac{a}{b}\right\rfloor~\times~b)y_0\\ & = ay_0+b(x_0-\left\lfloor\frac{a}{b}\right\rfloor~y_0) \\ \end{align} \]

根據對應系數相等,顯然有\(x=y_0,y=x_0-\left\lfloor\frac{a}{b}\right\rfloor~y_0\)。考慮他的一組特解:當\(b=0\)時,顯然\(x=1,y=0\)成立。

求上述方程的所有解

假設求出的該方程的一組特解\(x=x_0,y=y_0\),則該方程的所有解為\(x=x_0+\frac{k~\times~b}{gcd(a,b)},y=y_0-\frac{k~\times~a}{gcd(a,b)}\)

十、素數:

有且僅有\(1\)和本身兩個因子的數是素數

十一、埃拉托色尼篩法:

對每個數只篩掉它的倍數。

int pcnt;
int prime[maxn];
bool is_not_prime[maxn];

void Get_Prime(int x) {
	is_not_prime[1]=true;
	for(int i=1;i<=x;++i) if(!is_not_prime[i]) {
		prime[++pcnt]=i;
		for(int j=i*i;j<=x;j+=i;) is_not_prime[j]=true;
	}
}

十二:歐拉篩法

對每個數只被他的最小素因子篩掉

int pcnt;
int prime[maxn];
bool is_not_prime[maxn];

void Get_Prime(int x) {
	is_not_prime[1]=true;
	for(int i=2;i<=x;++i) {
		if(!is_not_prime[i]) prime[++pcnt];
		for(int j=1;j<=pcnt;++j) {
			if(i*prime[j] > x) break;
			is_not_prime[i*prime[j]]=true;
			if(!(i%prime[j])) break;
		}
	}
}

十三:在\(O(nlogn)\)時間內篩除\(n\)以內所有數的素因子

對於每個數記錄自己的最小素因子。對於第每個數,迭代將每個數除以自己的最小素因子。

int pcnt;
int prime[maxn],pre[maxn];
bool is_not_prime[maxn];

void Get_Prime(int x) {
	is_not_prime[1]=true;
	for(int i=2;i<=x;++i) {
		if(!is_not_prime[i]) prime[++pcnt],pre[i]=pcnt;
		for(rg int j=1;j<=pcnt;++j) {
			if(i*prime[j] > x) break;
			is_not_prime[i*prime[j]]=true;
			pre[i*prime[j]]=j;
			if(!(i%prime[j])) break;
		}
	}
}

void ans(int x) {
	for(int i=1;i<=x;++i) {
		printf("%d:",i);
		int di=i;
		while(di != 1) printf("%d",prime[pre[di]]),di/=prime[pre[di]];
		putchar('\n');
	}
}

十四、唯一分解定理:

\(\forall~x~\in~Z^*\),存在且僅存在一個形如\(x=p_1^{c_1}~p_2^{c_2}~...~p_k^{c_k}\)的等式。其中滿足\(p_i ~<~p_{i+1},p_i\)為質數,\(c_i~\in~Z\)

則對於\(a,b\)\(gcd,lcm\),其唯一分解式對應位置的指數取\(\min,\max\)即為對應的\(gcd,lcm\)的唯一分解式

十五、歐拉phi函數:

定義:\(\phi(n)\)\([1,n)\)中與\(n\)互質的數的個數

\(\phi(n)~=~n~(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k})\)

其中\(p_i\)\(n\)的唯一分解式對應底數。

證明:不妨設\(n\)只有\(p,q\)兩個因數。否則做數學歸納

則與\(n\)互質的數的個數為\(n\)減去\(p\)的倍數和\(q\)的倍數。根據容斥原理,應加回\((pq)\)的倍數。即

\[\begin{align} \phi(n) & = ~n-\frac{n}{p}-\frac{n}{q}+\frac{n}{pq}\\ & = ~n\left(1-\frac{1}{p}-\frac{1}{q}-\frac{1}{pq}\right)\\ & = ~n\left(1-\frac{1}{p}\right) \left(1-\frac{1}{q}\right) \end{align} \]

對於\(n\)有更多因數的情況,可以依據唯一分解定理做數學歸納。證畢。

求單個數字的\(\phi\)函數:

暴力枚舉質因數。復雜度\(O(\sqrt{n})\)

埃拉托色尼篩法:

對每個質數,修改他的倍數的\(phi\)函數值

int pcnt;
int prime[maxn],phi[maxn];
bool is_not_prime[maxn];

void euler(int x) {
	for(int i=1;i<=x;++i) phi[i]=i;
	for(int i=2;i<=x;++i) if(!is_not_prime[i]) {
		prime[++pcnt]=i;phi[i]=i-1;
		for(rg int j=i*i;j<=x;j+=i) {
			is_not_prime[j]=true;
			phi[j]=phi[j]/i*(i-1);
		}
	}
}

歐拉篩:

對每個數,只被他的最小質因子篩掉。

考慮通過一個質因子求出他的歐拉函數值。

引理:\(\forall x\)為質數,顯然\(\phi(x)=x-1\)
定理一:\(\forall~x~\in~Z^*,p|x\),若\(\frac{x}{p}\)\(p\)互質,則\(\phi(x)=\phi(\frac{x}{p})~\times~p\)
證明:

不妨設 \(x\) 有且僅有 \(p,q\) 兩個質因子,否則對\(q\)做數學歸納,不失一般性

\(q~=~\frac{x}{p}\)

於是由容斥原理有

\[\phi(x)~=~x~-~\frac{x}{p}~-~\frac{x}{q}~+~\frac{x}{pq} \]

\[\phi(\frac{x}{p})~=~\frac{x}{p}~-\frac{x}{p^2}~-~\frac{x}{pq}+~\frac{x}{p^2q} \]

上式除以下式,得

\[\frac{\phi(x)}{\phi\frac{x}{p}}=p \]

移項整理后,原式得證。

證畢。

定理二:\(\forall~x~\in~Z^*,p|x\),若\(\frac{x}{p}\)\(p\)互質,則\(\phi(x)=\phi(\frac{x}{p})~\times~(p-1)\)
證明:

易證\(phi\)函數為積性函數。因為\(\frac{x}{p}\)\(p\)互質,於是\(\phi(x)=\phi(\frac{x}{p})~\times~\phi(p)\)

又因為\(p\)是一個質數,於是根據引理,\(\phi(p)=p-1\)

原式得證。

證畢。

於是對於每個數,若他是質數,則應用引理,否則在篩時,若最小質因子與他互質,則應用定理二,否則應用定理一。

int pcnt;
int prime[maxn],phi[maxn];
bool is_not_prime[maxn];

void euler(int x) {
	phi[1]=1;
	is_not_prime[1]=true;
	for(int i=1;i<=x;++i) {
		if(!is_not_prime[i]) prime[++pcnt]=i,phi[i]=i-1;
		for(int j=1;j<=pcnt;++j) {
			if(i*prime[j] > x) break;
			is_not_prime[i * prime[j]]=true;
			if(!(i%prime[j])) {phi[i*prime[j]]=phi[i]*prime[j];break;}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}

十六、模方程:

定義:\(\forall a,b ~\in~Z\),若\(a~Mod~m~=~b~Mod~m\) 則稱作\(a,b\)在模\(m\)域下同余。記做\(a~\equiv~b~(Mod~m)\)

同余式兩邊支持同時加、減、乘同一個數字,但不支持除法。

十七、模逆元:

\(\forall~a~\in~Z\),若\(\exists~x~\in~Z,s.t.~ax~\equiv~1~(Mod~m)\)則稱\(x\)\(a\)在模\(m\)域下的逆元。在模\(m\)域下,任何一個整數除以\(a\)完全等價於乘\(x\)

一般而言,\(m\)為質數是\(a\)存在逆元的充分條件

十八、逆元的求法

單個數求逆元

解方程\(ax~\equiv~1~(Mod~m)\),發現等價於\(ax+km=1\)。直接使用\(exgcd\)求得答案即可。

線性篩逆元:

\(x\)的逆元為\(x^{-1}\),數組表示為\(inv_x\)

則有線性遞推式:\(inv_i~=~(-\left\lfloor\frac{m}{i}\right\rfloor~\times~inv_{m~Mod~i}+m)~Mod~m\)

證明:

對於所有的\(i\),寫出他的帶余除法表達式:

\[m~=~ki~+~r,r~\in~[0,i) \]

\(Mod~m\)域下有:

\[ki~+~r~\equiv~0~(Mod~m) \]

等式兩側同乘\(i^{-1}~\times~r^{-1}\)

化簡,整理得到:

\[i^{-1}~\equiv~-kr^{-1} (Mod m) \]

因為\(k~=~\left\lfloor\frac{m}{i}\right\rfloor\),原式得證。

int inv[maxn];

void Get_inv(int x,int p) {
	inv[1]=1;
	for(int i=2;i<=x;++i) inv[i]=(p-p/i)*inv[p%i]%p;
}


免責聲明!

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



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