數論剛掃過一次,雖然不是太全面(那就只能後邊再補起來了),爲了爲後邊的複習作準備,就來整理了一下。
這裏大致把內容分爲幾個板塊,方便一塊兒複習,要看刷的題,確定仍是隻能去
https://docs.qq.com/sheet/DTkVGZFpkQkhRS2N1?tab=25ta5r&c=D346A0LZ0算法
對於兩個正整數𝑝和𝑞,若存在正整數𝑥,知足𝑝𝑥 = 𝑞,則
稱𝑝整除𝑞 ,記做𝑝|𝑞。
整除的相關性質:
1.自反性:𝑝|𝑝
2.傳遞性:𝑝|𝑞, 𝑞|𝑟 → 𝑝|𝑟
3.反對稱性:𝑝|𝑞, 𝑞|𝑝 → 𝑝 = 𝑞優化
對於正整數𝑎, 𝑏,存在惟一一對整數(𝑞, 𝑟),知足𝑎 = 𝑏𝑞 + 𝑟 且0 ≤ 𝑟 < 𝑏。稱𝑞爲商,𝑟爲餘數。spa
下取整: \(\lfloor x \rfloor\) = max{𝑘 ∈ 𝑍|𝑘 ≤ 𝑥}
上取整: \(\lceil 𝑥 \rceil\) = min{𝑘 ∈ 𝑍|𝑘 ≥ 𝑥}
能夠發現𝑞 = \(\lfloor \frac{a}{b} \rfloor\)code
對於正整數𝑎, 𝑏,定義模運算爲
𝑎 mod 𝑏 = 𝑎 − \(\lfloor \frac{a}{b} \rfloor\)⌋𝑏
注意在C++中,除法返回的結果是向0取整。遞歸
固然,這個也就灰常簡單了,因此直接貼代碼。。。
inline LL GCD(LL A,LL B) { return !B ? A : GCD(B,A%B); }
get
不定方程𝑎𝑥 + 𝑏𝑦 = 𝑐有解,當且僅當gcd (𝑥,𝑦) | c.class
必要性顯然
充分性證實能夠考慮在求解gcd的時候遞歸構造解。擴展
每一次令a = a',b = b'-a' \(\lfloor \frac{x}{y} \rfloor\) 。
邊界條件是當y = 0時,a = \(\frac{c}{x}\),b = 0。
(Of Course 裴蜀定理確定不可能就這!)
(因此能夠問一問數競大佬萌。。。(順便獻上個人膝蓋))
(QQ:849387128 630118646)gc
主要思想就是先找到一組通解,在進行變化求出想要的類型的全部解。
求特解:im
inline LL Ex_GCD(LL A,LL B) { if(!B) { X=1; Y=0; return A; } LL Res=Ex_GCD(B,A%B); LL Temp=X; X=Y; Y=Temp-(A/B)*Y; return Res; }
求出來以後的就是X0了。
對於以後的過程,通常會要求算出最小非零整數解。
inline bool MLE(LL a,LL b,LL n) { LL x0; LL D=Ex_gcd(a,n); if(b%D) return false; x0=X*(b/D)%n; if(x0>0) Mans=min(Mans,x0); for(int i=1;i<=D;i++){ if(((x0+i*(n/D))%n)>0) Mans=min(Mans,((x0+i*(n/D))%n)); } return true; }
對於一個大於1的整數𝑥,若是它不被任何1 < 𝑦 < 𝑥的整數
𝑦整除,那麼稱𝑥爲質數或素數,不然稱𝑥爲合數。
質數有無窮多個。
如有有限個質數𝑝1 \(\cdots\) 𝑝𝑚,則令𝑛 = \(\prod_{i = 1}^{m} pi\),則 𝑛 + 1 不能被𝑝1 \(\cdots\) 𝑝𝑚整除,因此 𝑛 + 1 也是質數。
設\(\leq\) 𝑛的質數有𝜋(𝑛)個,則\(\pi \left( n \right) = O\left( \frac{n}{logn} \right)\)
任何正整數都能惟一表示成一些質數的冪的乘積。
(因爲本蒟蒻沒怎麼去了解其餘篩法,此處就先只寫一個最經常使用到的線性歐拉篩)
咱們想要獲得一個\(O \left( n \right)\)的算法。
在埃氏篩中,咱們發現了這樣一個問題:每個合數會被篩不少次,好比30這個數就被2,3,5各篩了一次。
能不能優化這個過程呢?換句話說,能不能使得每個合數都只被篩一次呢?
答案是確定的
咱們嘗試讓一個合數只在枚舉到它最小的質因子的時候被篩掉。
回顧埃氏篩的過程,當咱們到達𝑖時,咱們順次枚舉當前的全部質數,而且篩掉這個質數乘𝑖。由於咱們要讓這個質數是篩掉的合數的最小質因子,因此若是𝑖這個數包含𝑝這個質因子,那麼大於𝑝的全部質數就不用枚舉了,由於若是繼續枚舉獲得的數最小質因子都會小於當前枚舉的質數。
好比如今咱們有2,3,5這三個質數,如今i是6,那麼咱們枚舉到2的時候發現2是6的質因子,因此後面的3和5都不用枚舉了,由於 3 × 6,5 × 6 的最小質因子是2,而不是3和5。
(這個過程是照搬的,因此我沒有把排版弄太好。。。)
flag[1]=1; for(int i=2;i<=n;i++) { if(!flag[i])prime[++num]=i; for(int j=1;j<=num&&prime[j]*i<=n;j++) { flag[i*prime[j]]=1; if(i%prime[j]==0)break; } }
(先寫到這兒,下週再來寫,嘿嘿嘿QwQ)