今天鍾長者講課吖qqqq
一、質數
有一個定理: 設p爲質數,若p | ab ,則 p | a或者p | b;
二、整數唯一分解定理
這個證明是用的反證法:
1.存在性
設立N爲不滿足條件的最小的數
若N爲質數 顯然不成立
若N爲合數 由於N = an 則n也不能分解 因此不成立
2.唯一性
設N爲不可以被整除的最小的數
若N爲質數 因爲N = N^1 顯然不成立
若N爲合數 N = P * N / P 因爲N爲最小的,而 N / P卻更小,因此不成立
證畢
三、Miller_Rabin素性測試
如果N爲素數,取a < n;
設n - 1 = d * 2 ^ r
則下列兩個結論中必定滿足一個:
1.
2.
先貼代碼吧:
其中定義的gg[]數組就是8個素數
證明:
我們使用平方差公式,運用歐拉定理進行證明:
(手寫qwq)
(像素好低啊q)
三、篩法
埃氏篩,歐拉篩昨天講了,代碼也放在昨天了,今天就不再提起了
四、最大公因數
歐幾里得算法的核心思想:
gcd(a,b) = gcd(b,a - b)
推導得出: gcd(a,b) = gcd(a,a % b)
證明:
反證法:
五、裴蜀定理
還有,解釋了一下充要條件qqq
證明過程:
這裏可以用裴蜀定理證明這個定理: 設p爲質數,若p | ab ,則 p | a或者p | b;
六、拓展歐幾里得
求 ax + by = gcd(a,b)的一組解(x,y)
推導式:
將 a % b 改寫爲 a - a / b * b
Code:
七、中國剩餘定理:
正經做法:
證明過程:
這個題做法即爲兩兩合併
對於k個方程
則進行k - 1次合併
舉個栗子:
邪門做法(大數翻倍法):
我們一直對於兩個方程式中
不斷地將x += p1
直到滿足第二個式子
然後對於這個進行排序,選取較大的數
則可得其時間複雜度爲: O(p1 + p2 + ... +pn - max(p1,p2,...,pn));
被卡的情況:兩個10 ^ 9的p的時候
八、BSGS算法 (Baby Step Giant Step)
qwq(北上廣深)(拔山蓋世)算法
這個問題主要是求給定a,b,p,求最小的非負整數x,滿足 ax ≡ b(mod p)
方法:
r * a ^ sqrt(m) = b;
左右同乘逆元
則變爲: r = b * -sqrt(m);
我們可以採用分塊:
將其分爲 sqrt(m) * sqrt(m)的形式
還有一個排序的步驟,便於二分
然後詢問在第一行中有沒有數可以使得r = b * a ^ -sqrt(m)
Code:
#define ll long long int size; bool erfen(int x) { int l = 0; int r = size; while(l + 1 != r) { int m = (l + r) >> 1; if(z[m] >= x) r = m; else l = m; } return z[r] == x; } int kuaisumi(int base,int b,int p) { int ans; while(b) { if(b & 1) ans *= base; base *= base; b >>= 1; } return ans; } int bsgs(int a,int b,int p) { size = sqrt(p); int nowv = 1; for(int i=1;i<=size;i++) { nowv = (ll)nowv * a % p; z[i] = nowv; if(z[i] == b) return i; } sort(z + 1,z + size + 1); for(int i=2;(i-1)*size+1<=p;i++) { int y =(ll)b * kuaisumi(kuaisumi(a,size * (i - 1),p),p - 2,p); if(erfen(y)) { for(int j=(i-1)*size+1;j<=i*size;j++) if(kuaisumi(a,j,p) == b) return j; } } return -1; }
九、線性求逆元
#include<iostream> #include<cstdio> #include<algorithm> #define ll long long using namespace std; ll n,p,m,k,r,x; ll inv[20000528]; int main() { scanf("%lld%lld",&n,&p); inv[1]=1; if(n>=1) printf("1\n"); for(int i=2;i<=n;i++) { inv[i]=p-(p/i)*inv[p%i]%p; printf("%lld\n",inv[i]); } return 0; }
九、積性函數
定義:
若gcd(x,y) = 1,有f(xy) = f(x) * f(y)
常見的積性函數:
歐拉函數爲積性函數的證明(因子數目與因子之和的大同小異)
莫比烏斯函數:
mu[i]
對於 i 將其分解(唯一分解定理) 爲 p1 ^ r1 ...... pn ^ rn
設 r = max(r1,r2,...,rn);
設 k = r1 + r2 +...+ rn;
則:
mu[i] = 1 i == 1 的時候 mu[i] = 0 r > 1 的時候 mu[i] = (-1) ^ k r == 1 的時候
Code:
這其中;
phi[] 歐拉函數
mu[] 莫比烏斯函數
線性篩求積性函數
莫比烏斯是積性函數的證明:(這個要用到組合數,長者說明天再講的)
留個坑,有時間再補吧
十、莫比烏斯反演
F(n)和f(n)是定義在非負整數集合上的兩個函數:
證明:
qqq
還有一些老師發的Code:
Miller_Rabin
int gg[8] = {2,3,5,7,13,29,37,89}; bool miller_rabin(int a,int n) { int d=n-1,r=0; while (d%2==0) d/=2,r++; int x = kuaisumi(a,d,n); if (x==1) return true; for (int i=0;i<r;i++) { if (x==n-1) return true; x=(long long)x*x%n; } return false; } bool is_prime(int n) { if (n<=1) return false; for (int a=0;a<8;a++) if (n==gg[a]) return true; for (int a=0;a<8;a++) if (!miller_rabin(gg[a],n)) return false; return true; }
線性篩積性函數中的歐拉函數和莫比烏斯函數
memset(not_prime,0,sizeof(not_prime)); for (int i=2;i<=n;i++) { if (!not_prime[i]) { prime[++ prime_cnt] = i; phi[i] = i-1; mu[i] = -1; } for (int j=1;j<=prime_cnt;j++) { int x = i * prime[j]; if (x>n) break; not_prime[x] = true; phi[x] = phi[i] * phi[prime[j]]; mu[x] = mu[i] * mu[prime[j]]; if (i % prime[j] == 0) { phi[x] = phi[i] * prime[j]; mu[x] = 0; break; } } }