我讀書少,又是鄉下來的,沒寫過多少程式,
所以我只能默默的看著別人上分,時不時標個電,
有時間也當個資讀講師,這樣好像可以假裝自己是資訊組。
以下\(p\)代表質數,\(m\)代表正整數
其他字母默認為整數
int GCD(int a, int b){
if(!b){
return a;
}
return GCD(b, a%b);
}
因為每輾轉兩次\(a\)和\(b\)都至少減半,故複雜度為\(\mathcal{O}\left(\log \min(a, b)\right)\)
//for c++14
#include <algorithm>
using namespace std;
int a=32725, b=48763;
int g = __gcd(a, b);
//g = 11#define int long long
using namespace std;
const int m = 1e9+7;
int fastpow(int a, int n){
if(!n){
return 1;
}
if(n&1){
return (a*fastpow(a, n^1))%m;
}
int tmp = fastpow(a, n>>1);
return (tmp*tmp)%m;
}\(\mathcal{O}(\log n)\)
其實矩陣乘法也是一種函數合成
若\(m_1, m_2, \cdots, m_n\)兩兩互質
設\(\displaystyle\prod_{i=1}^n m_i=M\)
則以上同餘方程在\(\displaystyle\operatorname{mod} M\)下有唯一解
笛卡爾積
數列
質因數分解
因數個數
因數總和
因為一個合數必有不超過\(\lfloor\sqrt{n}\rfloor\)的質因數,故試除\(\left[\ 2,\sqrt{n}\ \right]\)中的所有整數即可判斷
\(\mathcal{O}(\sqrt{n})\)
為隨機化算法,但在特定範圍內可以只驗很少個base而確定一個數是否為質數
\(\mathcal{O}(k\log^3 n)\),其中\(k\)為base的個數
#include <vector>
#include <bitset>
using namespace std;
bitset<10000000> visited;
vector<int> prime;
void sieve1(int n){
//初始化
visited.reset();
prime.clear();
//篩法
for(int i=2; i<=n; i++){
if(!visited[i]){
prime.push_back(i);
}
for(int j=i<<1; j<=n; j+=i){
visited[j] = 1;
}
}
}#include <vector>
#include <bitset>
using namespace std;
bitset<10000000> visited;
vector<int> prime;
void sieve2(int n){
//初始化
visited.reset();
prime.clear();
//篩法
for(int i=2; i<=n; i++){
if(!visited[i]){
prime.push_back(i);
for(int j=i<<1; j<=n; j+=i){
visited[j] = 1;
}
}
}
}#include <vector>
#include <bitset>
using namespace std;
bitset<10000000> visited;
vector<int> prime;
void sieve3(int n){
//初始化
visited.reset();
prime.clear();
//篩法
for(int i=2; i<=n; i++){
if(!visited[i]){
prime.push_back(i);
}
for(const auto &k: prime){
if(i*k>n) break;
visited[i*k] = 1;
if(i%k==0) break;
}
}
}保證\(k\)是\(ik\)的最小質因數
只篩掉每個數的質數倍
//篩法
for(int i=2; i<=n; i++){
if(!visited[i]){
prime.push_back(i);
}
for(const auto &k: prime){
if(i*k>n) break;
visited[i*k] = 1;
if(i%k==0) break;
}
}保證\(k\)是\(ik\)的最小質因數
只篩掉每個數的質數倍
因此,所有合數都只會被自己最小的質因數篩掉
故複雜度為\(\mathcal{O}(n)\)
因此可以遞迴出\(\varphi(\text{合數})\)的值
\(\displaystyle\prod_{i\in A}i=\prod_{x\in A'}x\equiv\)
\(\displaystyle\prod_{i\in A}ia=a^{\varphi(n)}\)
\(\displaystyle\prod_{i\in A}i\pmod{m}\)
\(\displaystyle 1\equiv\)
\(\displaystyle a^{\varphi(m)}\)
\(\displaystyle\pmod{m}\)
\(\varphi(m)\)已知時,計算模逆元為\(\mathcal{O}(\log\varphi(m))\)
我們可以用輾轉相除法構造出一組解\(x, y\)
可遞迴出\(ax+by=g\)的最小解
int x, y, g;
void euclid(int a, int b){
if(!b){
x = 1;
y = 0;
g = a;
return;
}
euclid(b, a%b);
swap(x, y);
y -= a/b*x+a/g;
x += b/g;
}\(\mathcal{O}(\log a)\)
如果\(n\)太大時,要計算\(\displaystyle\binom{n}{m}\operatorname{mod} M\)
因為需要取模逆元,故為\(\mathcal{O}(m+\log M)\)