第四章 数学知识【完结】
本文的所有內容模板都來自于y總
目錄
- 試除法判定質數
- 試除法分解質因數
- 樸素篩法求素數
- 埃氏篩法求素數
- 線性篩法
- 試除法求所有約數
- 約數個數和約數之和
- 歐幾里得算法
- 求歐拉函數
- 篩法求歐拉函數 【不熟】
- 快速冪
- 擴展歐幾里得算法
- 中國剩余定理 【未解決】
- 高斯消元 【不熟】
- 求組合數 【不熟】
- 容斥定理 【不熟】
- 博弈論【不會】
試除法判定質數
866. 試除法判定質數
時間復雜度是根號n
試除法分解質因數
867. 分解質因數
時間復雜度是 logn 到根號n 之間
樸素篩法求素數
時間復雜度: O(nlogn)
int primes[N], cnt; // primes[]存儲所有素數 bool st[N]; // st[x]存儲x是否被篩掉void get_primes(int n) {for (int i = 2; i <= n; i ++ ){if (st[i]) continue;primes[cnt ++ ] = i;for (int j = i + i; j <= n; j += i)st[j] = true;} }埃氏篩法求素數
時間復雜度: O(nloglogn)
int cnt; // 存儲素數個數 bool hush[N]; // st[x]存儲x是否被篩掉 for(int i=2;i<=n;i++){if(!hush[i]){cnt++;for(int j=i+i;j<=n;j+=i) hush[j]=true;}}線性篩法
868. 篩質數
你會發現: 用埃氏篩法的話,有一些數是篩了多遍的。
例: 6 用 2篩過一遍,用3又篩過一遍。
那么線性篩法就來了,它對于每一個數都只篩一遍是線性的,當要篩的數特別多的時候。
線性篩法幾乎快埃氏篩法一倍的速度。
下面的總結來自于: Acwing的評論區,我從中摘抄了里面的精華。
線性篩法的原理:
- 核心:1~n內的合數只會被其最小質因子篩掉.
- 原理:1~n之內的任何一個合數一定會被篩掉,而且篩的時候只用最小質因子來篩,
然后每一個數都只有一個最小質因子,因此每個數都只會被篩一次,因此線性篩法是線性的.
關于線性篩的解釋:
枚舉到i的最小質因子的時候就會停下來,即”if(i%primes[j]==0) break;”。
因為從小到大枚舉的所有質數,所以當”i%primes[j]!=0”時,primes[j]一定小于i的最小質因子,
primes[j]一定是primes[j]i的最小質因子.
因為是從小到大枚舉的所有質數,所以當”i%primes[j]==0”時,primes[j]一定是i的最小質因子,
而primes[j]又是primes[j]的最小質因子,因此primes[j]是iprimes[j]的最小質因子.
關于for循環的解釋:
注:首先要把握住一個重點:我們枚舉的時候是從小到大枚舉的所有質數
- 1.當i%primes[j]==0時,因為是從小到大枚舉的所有質數,所以primes[j]就是i的最小質因子,而primes[j]又是其本身
primes[j]的最小質因子,因此當i%primes[j]==0時,primes[j]是primes[j]i的最小質因子. - 2.當i%primes[j]!=0時,因為是從小到大枚舉的所有質數,且此時并沒有出現過有質數滿足i%primes[j]==0,
因此此時的primes[j]一定小于i的最小質因子,而primes[j]又是其本身primes[j]的最小質因子,
所以當i%primes[j]!=0時,primes[j]也是primes[j]i的最小質因子. - 3.綜合1,2得知,在內層for循環里面無論何時,primes[j]都是primes[j]i的最小質因子,因此”st[primes[j]i]=true”
語句就是用primes[j]i這個數的最小質因子來篩掉這個數.
for (int j = 0; primes[j] <= n / i; j ++)不需要寫成 for (int j = 0; j < cnt && primes[j] <= n / i; j ++)理由:
如果 i 是合數,那它有最小質因子 prime[j],所以循環會在枚舉到 prime[j] 時 break 掉;
如果 i 是質數,則由于上面剛把 i 加到了 primes 數組中,所以 prime[j] 枚舉到最后一個時正好等于 i,
所以也會 break 掉。因此 j 不會大于等于當前的 cnt
試除法求所有約數
869. 試除法求約數
vector<int> get_divisors(int x) {vector<int> res;for (int i = 1; i <= x / i; i ++ )if (x % i == 0){res.push_back(i);if (i != x / i) res.push_back(x / i);//避免 36 6*6 進入2個6的情況}sort(res.begin(), res.end());return res; }約數個數和約數之和
870. 約數個數
871. 約數之和
約數個數公式的解析:
約數之和公式解析:
歐幾里得算法
872. 最大公約數
int gcd(int a, int b) {return b ? gcd(b, a % b) : a; }求歐拉函數
873. 歐拉函數
篩法求歐拉函數 【不熟】
874. 篩法求歐拉函數
int primes[N], cnt; // primes[]存儲所有素數 int euler[N]; // 存儲每個數的歐拉函數 bool st[N]; // st[x]存儲x是否被篩掉void get_eulers(int n) {euler[1] = 1;for (int i = 2; i <= n; i ++ ){if (!st[i]){primes[cnt ++ ] = i;euler[i] = i - 1;}for (int j = 0; primes[j] <= n / i; j ++ ){int t = primes[j] * i;st[t] = true;if (i % primes[j] == 0){euler[t] = euler[i] * primes[j];break;}euler[t] = euler[i] * (primes[j] - 1);}} }快速冪
875. 快速冪
876. 快速冪求逆元
迭代法:
遞歸法:
#include<cstdio> #include<iostream> using namespace std; typedef long long int ll; ll f(ll a,ll b,ll c) {if(!b) return 1;ll res=f(a,b>>1,c);if(b&1) return a*res%c*res%c;else return res*res%c; } int main(void) {int n; scanf("%d",&n);while(n--){ll a,b,c; scanf("%lld%lld%lld",&a,&b,&c);cout<<f(a,b,c)<<endl;}return 0; }擴展歐幾里得算法
877. 擴展歐幾里得算法
878. 線性同余方程
中國剩余定理 【未解決】
204. 表達整數的奇怪方式
高斯消元 【不熟】
883. 高斯消元解線性方程組
884. 高斯消元解異或線性方程組
求組合數 【不熟】
885. 求組合數 I
886. 求組合數 II
887. 求組合數 III
888. 求組合數 IV
AcWing 889. 滿足條件的01序列 【卡特蘭數】
容斥定理 【不熟】
890. 能被整除的數
博弈論【不會】
891. Nim游戲
892. 臺階-Nim游戲
893. 集合-Nim游戲
894. 拆分-Nim游戲
總結
以上是生活随笔為你收集整理的第四章 数学知识【完结】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第二章 数据结构 【完结】
- 下一篇: 双端队列【deque】的常见用法