要命的逆元
Day 2 基礎數論演算法
from hzwer
by Zxsure
基礎概念:
假設 m 和 n 是整數,且 m 不是 0,則 m 整除 n 指的是 n 是 m 的倍
數,即存在整數 k,使得 n = mk
如果 m 整除 a - b,我們就說 a 與 b 模 m 同餘並記
\[\ a\ ≡ \ b(\mod \ m) \]例題:
- 證明:如果一個數每一位加起來可以被 3 整除,那這個數就可以被 3
整除?
素數
時間複雜度
\[{O\sqrt n} \]for(2~(sqrt)n)
check(i % m == 0)
素數篩法
在數列中篩去 2 ,3 ,5,7,8,9的倍數;
時間複雜度:
\[{n\ log\ log n} \]例題
-
分解質因數
-
假設素數是有限的,假設素數只有有限的n個,最大的一個素數是p。
\[{q_{max}\ = (2×3×4\cdots×p)+1} \] -
不能被所有的素數整除就找到更大的素數。
素數的唯一分解
若整數 N≥2,那麼 N 一定可以唯一地表示為若干素數的乘積。
形如
- \({N = p_1^r ×p_2^r× …×p_k^r(p_i 為素數 , r_i ≥ 0)}\)
最小公倍數
\[gcd(a,b)=1(a,b\ 互質) \]\[gcd(a,b) = gcd(b ,a\ mod\ b) \]return b = 0 ? a : gcd(b,a % b)
歐幾里得演算法
• \({gcd(a,b)=gcd(b, a\ mod \ b)}\)
• 設 g = gcd(a, b),r = a mod b,我們可以知道 a = kg + r
• 再根據 g 的最大公因數的性質(也就是同時整除a和b)就可以知道 g 也整除 r。
• 同樣的,我們也可以證明,g 是同時整除 b 和 r 的最大的整數,這樣,這個等式就成立了。
逆元
\[X*X^{-1}=1(mod\ p) \]條件 :解決同餘意義下,無法進行除法的問題
推理:
\[\left\{ \begin{array}{c} {(a/b)\ mod\ p\not= \frac{a\ mod\ p}{b\ mod\ p}}\\ {(a/b)\ mod\ p\ = (a\ mod\ p)*(b^{-1}\ mod \ p)} \end{array} \right. \]推理過程
-
我們有: inv(x)⋅x≡1 (mod p), 又據費馬小定理:x^(p-1) ≡ 1 (mod p)
-
故有:inv(x)⋅x ≡ x^(p-1) (mod p) ,兩邊同時除以 x 有:
-
inv(x) ≡ x^(p-2) (mod p) ,這就是模質數意義下的逆元求法。
-
\(inv\) 表示逆元
結論
\[a^{-1}=a^{p-2} \]快速冪
-
求快速冪 \(a^b\)
-
預處理 \({a^1\ a^2\ a^3\ \cdots\ a^{2n} }\),對b進行二進位制拆分
-
如:\({a^{21}=a^{16}*a^{4}*a^{1}}\)
練習題
CF1209A.Paint the Numbers (900)
題面:
-
給 n 個數 a1 ~ an。要求你把它們分成 k 組,使得每⼀組中的數,都能被這一組最小值整除。問 k 最小是多少?
-
n <= 100, ai <= 10000
思路 :
-
將序列排序,從頭往後一次考慮最小數
-
貪心+模擬
-
以當前最小數去找到與其相關的倍陣列成一組(貪)
-
貪⼼篩法,每次取沒被篩掉的最小元素,篩掉它的倍數(PPT)
Code :
CF486A.Calculating Function (1100)
題面 :
-
計算函式 f(n) = -1 + 2 - 3 + .. + ( - 1)^n * n
-
n <= 10^15
思路 :
-
n 為奇數,答案是 -(n+1)/2
-
n 為偶數,答案是 n / 2
CF492B.Vanya and Lanterns (1200)
題面 :
-
一個長為 L 的街道(左端點是 0,右端點是 L)上有 n 個相同的燈,第 i 個燈放置的位置是 ai
-
問燈的半徑至少要是多少,才能使得整個街道都有燈光。
-
n <= 1000, L <= 10^9
思路:
-
暴力找到燈之間的距離一半最大值
-
再比較兩邊界的的燈的距離。
CF570B. Simple Game (1300)
題面:
-
給 n,m,求⼀個數 a (1 ≤ a ≤ n),使得當 c 在 1 到 n 的整數中隨機取值時, |c − a| < |c − m| 成立的概率最大。
-
n, m <= 10^9, m <= n
思路:
- 分 2m ≤ n 和 2m > n 討論
CF546B.Soldier and Badges (1300)
題面 :
-
給 n 個數,每次操作可以將一個數 +1,要使這 n 個數都不相同, 求至少要加多少?
-
n <= 3000
思路:
- 排序,挨個+1
401C.Team(1400)
題面:
-
構造一個 01 序列,包含 n 個 0,m 個 1
-
要求不存在連續 2 個 0,或 3 個 1
-
無解輸出 -1
-
1 ≤ n, m ≤ 10^6
思路:
-
判斷無解的情況下。
-
011和01進行構造
Code
/*
2020/10/3 20:59
CF401C Team
by BZQ
*/
#include<iostream>
using namespace std;
int n,m;
int main(){
cin >> n;
cin >> m;
if(m > n*2 + 2 || n > m+1) cout << -1;//判斷無解的情況
else
{
if(m > n*2){ //此處將 m >= n 的情況和 m > 2n 的情況做個合併。
for(int i = 1;i <= m - n*2; i++)//先對 m > 2n 進行預處理,之後操作一樣。
cout << "1";
m = 2 * n; //注意:在做完預處理後,現在的序列就相當於是一個滿011和01的序列,所以更新m;
}
if(m >= n){
for(int i = 1;i <= m - n; i++) // 先貪大後貪小
cout << "011";
for(int i = 1;i <= 2*n-m; i++)
cout << "01";
}
if(n > m){
cout << "0"; // 回覆思路 1 中的問題:以為無解的邊界為 n > m+1 故要想此時的 n > m 成立,當且僅當 n = m + 1;
for(int i = 1;i <= m;i++)
cout << "10";
}
}
return 0;
} //感謝觀看,
413C.Jeopardy!(1400)
題面:
-
給 n 個關卡,每個關卡得分為 ai,有 m 次機會可以選擇一個關卡通過後不得分,而將現有得分翻倍
-
你可以安排關卡的通過順序和策略,求最大得分
-
1 ≤ n, m ≤ 100
思路:
- 將可以翻倍關卡放在後頭,且按從一到n排序,依次貪心
POJ2689. Prime Distance
題面 :
-
給定兩個整數 L, R (1 ≤ L ≤ R ≤ 2^31, R-L ≤ 10^6),
-
求閉區間[L, R] 中相鄰兩個素數的差最大是多少?
思路:
-
預處理\({\sqrt{2^{31}}}\);
-
暴力判斷
-
使用篩法求出 [2,√R] 之間的所有素數,對於每個素數 p ,把[L,R] 中能被 p 整除的數標記,即標記 i × p(⌈L/p⌉ ≤ i ≤ ⌊R/p⌋)為合數。
-
將篩出的素數進行相鄰兩兩比較,找出差最大的即可
235A.LCM Challenge (1600)
題面:
-
在小於n 的數中找三個數 a, b, c
-
最大化 lcm(a, b, c)
-
n <= 10^6
思路:
- 在接近 n 的數內找三個兩兩互質的,小範圍暴力
NOIP2014. 解方程
題面:
已知多項式方程:
-
a_0+a_1x+a_2x^2+\cdots+a_nx^n=0a0+a1x+a2x2+⋯+anx**n=0
-
求這個方程在 [1,m][1,m] 內的整數解(nn 和 mm 均為正整數)。
思路:
-
暴力驗證[1,m]內的整數?係數太大,取模!
-
方程的解不會超過n個
-
如果\(x=x_0\)的時候,在對$p $ 取模後方程不成立,那麼原方程必然不成立
-
用比較小的質數驗證一個,先排除大部分
以上思路來源PPT,本人無思路,因為不會
作者 @Zxsure,轉載請宣告出處