intpartition(int arr[], int low, int high) { int pivot = arr[high]; int i = (low - 1);
for (int j = low; j <= high - 1; j++) { if (arr[j] <= pivot) { i++; swap(arr[i], arr[j]); } } // 替换到交界的位置 swap(arr[i + 1], arr[high]); return (i + 1); }
intpartition_r(int arr[], int low, int high) { srand(time(NULL)); int random = low + rand() % (high - low); // 与最高位交换即可 swap(arr[random], arr[high]); returnpartition(arr, low, high); }
voidquickSort(int arr[], int low, int high) { // 拆分问题 if (low < high) { // 排序 int pi = partition_r(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } }
string print(){ string ret; auto it = cur; for (int i = 0; i < 10; i++) { if (it == lst.begin()) break; it = prev(it); ret.push_back(*it); } reverse(ret.begin(), ret.end()); return ret; }
public: TextEditor() { cur = lst.begin(); }
voidaddText(string text){ for (char c : text) lst.insert(cur, c); }
intdeleteText(int k){ int ret = 0; while (k && cur != lst.begin()) { cur = prev(cur); cur = lst.erase(cur); k--; ret++; } return ret; }
string cursorLeft(int k){ while (k && cur != lst.begin()) { cur = prev(cur); k--; } returnprint(); }
string cursorRight(int k){ while (k && cur != lst.end()) { cur = next(cur); k--; } returnprint(); } };
voidaddText(string text){ for (char c:text) left.push(c); }
intdeleteText(int k){ k = min(k, (int)left.size()); for (int i = 0; i < k; i++) left.pop(); return k; }
string text(){ string res; for (int i = 0, k = min((int)left.size(), 10); i < k; i++) { res.insert(res.begin(), left.top()); left.pop(); } addText(res); return res; }
string cursorLeft(int k){ k = min(k, (int)left.size()); while (k--) { right.push(left.top()); left.pop(); } returntext(); }
string cursorRight(int k){ k = min(k, (int)right.size()); while (k--) { left.push(right.top()); right.pop(); } returntext(); } };
set
1 2 3 4 5 6 7 8 9 10 11 12
auto p1 = prev(s1.lb(x)); if (arr[*p1] > arr[x]) { s1.insert(x); for (auto p = next(s1.find(x)); p != s1.end(); p++) { int id = *p; if (arr[x] <= arr[id]) { dd.pub(id); } elsebreak; } rep (i, 0, sz(dd)) s1.erase(dd[i]); }
剩下3堆石子
(1,1,k)、(1,k,k)和(k,k,k)都是必胜态【都可以留下(k,k)必败态给对手】,
接下来对于任一个(a,b,c)都可以转化为(k+m, k+n, k+p)
而对于m,有3种情况,分别是 ① 三者相等,就是(k’,k’,k’),为必胜态。 ②
两者相等, 这样把k+m取完,留下必败态给对手,也是必胜态。 ③
三者不等,这种情况非常复杂,用简单的公式难以表达,我们可以观察到(1,2,3)是必败态,但是(1,2,4)是必胜态,两者只是相差一个石子。
LL C(int n, int m){ return fact[n]*a[n-m]%mod*a[m]%mod; }
逆元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// rsa 解密 求乘法逆元 // 辗转相除 voidexgcd(int a, int b, int& x, int& y){ if (b == 0) { x = 1, y = 0; return; } // x = y, y = x - a / b * y; exgcd(b, a % b, y, x); y -= a / b * x; }
// 32 to 127 chr // 加 mod e = (x % m + m) % m;
质因子
1 2 3 4 5 6 7 8 9 10 11 12
// C++ Version inteuler_phi(int n){ int ans = n; // 注意i = 2 for (int i = 2; i * i <= n; i++) if (n % i == 0) { ans = ans / i * (i - 1); while (n % i == 0) n /= i; } if (n > 1) ans = ans / n * (n - 1); return ans; }
// ! extend gcd 不可以使用ull 存在负值 ull a > -1 恒成立 inline ull mul(ull a, ull b, ull mod){ ull ans = 0; while( b > 0 ){ if(b & 1) ans = (ans + a) % mod; a = (a + a) % mod; b >>= 1; } return ans; }
ull quick_pow(ull a, ull b, ull mod){ ull res = 1; a %= mod; while(b) { if (b & 1) res = mul(res, a, mod); a = mul(a, a, mod); b >>= 1; } return res; }
// a mod b = a - y [x / y] (x) intmod(int a, int b){ return (a % b + b) % b; }
inline ull mul(ull a, ull b, ull mod){ ull ans = 0; while( b > 0 ){ if(b & 1) ans = (ans + a) % mod; a = (a + a) % mod; b >>= 1; } return ans; }
ull quick_pow(ull a, ull b, ull mod){ ull res = 1; a %= mod; while(b) { if (b & 1) res = mul(res, a, mod); a = mul(a, a, mod); b >>= 1; } return res; }
intgcd(int a, int b){ if (b == 0) return a; returngcd(b, a % b); }
// rsa 解密 求乘法逆元 // 辗转相除 voidexgcd(int a, int b, int& x, int& y){ if (b == 0) { x = 1, y = 0; return; } // x = y, y = x - a / b * y; exgcd(b, a % b, y, x); y -= a / b * x; }
// 32 to 127 chr // 加 mod e = (x % m + m) % m;
// C++ Version inteuler_phi(int n){ int ans = n; // 注意i = 2 for (int i = 2; i * i <= n; i++) if (n % i == 0) { ans = ans / i * (i - 1); while (n % i == 0) n /= i; } if (n > 1) ans = ans / n * (n - 1); return ans; }
int phi[MAXN]; voidinit(int n){ for (int i = 1; i <= n; i++) // 除1外没有数的欧拉函数是本身,所以如果phi[i] = i则说明未被筛到 phi[i] = i; for (int i = 2; i <= n; i++) if (phi[i] == i) // 未被筛到 for (int j = i; j <= n; j += i) // 所有含有该因子的数都进行一次操作 phi[j] = phi[j] / i * (i - 1); }
// 朴素法 // C++ Version list<int> breakdown(int N){ list<int> result; for (int i = 2; i * i <= N; i++) { if (N % i == 0) { // 如果 i 能够整除 N,说明 i 为 N 的一个质因子。 while (N % i == 0) N /= i; result.push_back(i); } } if (N != 1) { // 说明再经过操作之后 N 留下了一个素数 result.push_back(N); } return result; } // 求欧拉函数 // C++ Version inteuler_phi(int n){ int ans = n; for (int i = 2; i * i <= n; i++) if (n % i == 0) { // ans - ans / i ans = ans / i * (i - 1); while (n % i == 0) n /= i; } // 减去自身,1不需要减 if (n > 1) ans = ans / n * (n - 1); return ans; }
l-29 divide two integers
cannot use *, /, mod
divisor multiply - dividend
08.05 recursively multiply
64 1 + ... + n
&& replace if
repeat replace for
if b & 1 A + A res += A
l-371 sum of two integer
carry = a & b shift left
while(carry != 0)
l-332 reconstruct itinerary
seven bridge problem solved by Euler
in degree = out degree(except S/E)
? visited pop_back()
dfs(pop()), res.push_back(),reverse
the last number to end the search is last node
l-753 cracking the safe
? state not be visited
? how to visit n numbers
: set up a rule -- 0 - k 所有未经历过的状态
structnode { int x, y; node (int _x, int _y) { x = _x, y = _y; } }; vvi g; vvi dir = {{1, 0}, {0, -1}, {0, 1}, {-1, 0}}; int n, m; boolcheck(int x, int y){ return (0 <= x && x < n && 0 <= y && y < m && g[x][y] != 0); }
intbfs(int x, int y, int tx, int ty){ vvi vis(n, vi(m, 0)); queue<node> q; q.push(node(x, y)); vis[x][y] = 1; int cnt = 0; if (x == tx && y == ty) return0; while(q.size()) { int nn = q.size(); for (int i = 0; i < nn; i++) { node v = q.front(); q.pop(); x = v.x, y = v.y; for (int j = 0; j < 4; j++) { int xx = x + dir[j][0], yy = y + dir[j][1]; if (check(xx, yy)) { if (xx == tx && yy == ty) return cnt + 1; if (!vis[xx][yy]) { q.push(node(xx, yy)); vis[xx][yy] = 1; } } } } cnt++; } return-1; }
queue<tuple<int, int, int>> q; // pre-place start nodes; while (!q.empty()) { auto [u, mask, dist] = q.front(); q.pop(); if (mask == (1 << n) - 1) { ans = dist; break; } // 搜索相邻的节点 for (int v: graph[u]) { // 将 mask 的第 v 位置为 1 int mask_v = mask | (1 << v); // seen prevent repeated traversals if (!seen[v][mask_v]) { q.emplace(v, mask_v, dist + 1); seen[v][mask_v] = true; } } };
voiddfs(int v){ temppath.push_back(v); if(v == 0) { int need = 0, back = 0; for(int i = temppath.size() - 1; i >= 0; i--) { int id = temppath[i]; if(weight[id] > 0) { back += weight[id]; } else { if(back > (0 - weight[id])) { back += weight[id]; } else { need += ((0 - weight[id]) - back); back = 0; } } } if(need < minNeed) { minNeed = need; minBack = back; path = temppath; } elseif(need == minNeed && back < minBack) { minBack = back; path = temppath; } temppath.pop_back(); return ; } for(int i = 0; i < pre[v].size(); i++) dfs(pre[v][i]); temppath.pop_back(); }
// 0 - 1 bfs while (sz(q)) { int tt = q.front(); q.pop(); if (tt == b) break; vis[tt] = 1; rep (i, 0, sz(g[tt])) { int line = id[tt][i]; int tar = g[tt][i]; node nn(line, tt); int sign = 1; rep (i, 0, sz(par[tt])) { if (line == par[tt][i].line) { sign = 0; break; } } if (dis[tar] > dis[tt] + 1) { par[tar].clear(); dis[tar] = dis[tt] + 1; par[tar].pub(nn); ex[tar] = ex[tt] + sign; q.push(tar); } elseif (dis[tar] == dis[tt] + 1) { int ww = ex[tt] + sign; if (ww == ex[tar]) { par[tar].pub(nn); } elseif (ww < ex[tar]) { par[tar].clear(); par[tar].pub(nn); ex[tar] = ww; } q.push(tar); } } }
// A*
MST/强连通
minimum weight spanning tree 使得权值最短的路
Kruskal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 从最小边开始加入 // 并查集判断是否有环 // 无环则加入
sort(edgelist.begin(), edgelist.end());
int ans = 0;
for (auto edge : edgelist) { int w = edge[0], x = edge[1], y = edge[2]; // take that edge in MST if it does form a cycle if (s.find(x) != s.find(y)) { s.unite(x, y); ans += w; } }
// 二分 注意边界的处理,若不存在想要找的值得情况。 while(left < right) { // 是否加一取决于是否收敛 int mid = (left + right) / 2; // 不需要的结果 if (nn[mid] < diff) { left = mid + 1; } else { right = mid; } } // lower bound first element not less than i; // upper bound first element greater than i; greater<int> 则相反 auto lower = lower_bound(data.begin(), data.end(), i); if (lower != data.end()) int pos = lower - data.begin();
vector<int> c; staticintlowbit(int x){ return x & (-x); }
voidupdate(int x, int maxn, int v){ // x += 1 若nums从0开始 for(int i = x; i <= maxn; i += lowbit(i)) c[i] += v; } intgetsum(int x){ int sum = 0; for(int i = x; i >= 1; i -= lowbit(i)) sum += c[i]; return sum; }
intsumRange(int i, int j){ // 从i到j returngetsum(j) - getsum(i - 1); }
// 示例 intmain(){ int n = 5; c.assign(n + 1, 0); for (int i = 1; i <= n; i++) { update(i, n, 1); } cout << sumRange(2, 5); }
线段树
l-307 range sum query solutions
sqrt(n) blocks(known length)
binary indexed tree(Fenwick tree) 对操作数进行累加 (前面所有的操作数)
而非数值本身
l-1622 fancy-sequence
inverse order - add all multall opt - ax + b
combine opt 使用数组快于vector
1 2 3 4
voidoperator += (const node &t){ a = a * t.a%mod; b = (b * t.a + t.b)%mod; }
// ncr = (n - 1)Cr + (n - c)C(r - 1) // 未选取特定元素的组合 - 选取了特定元素的组合 // ncr longlongC(int n, int r){ if(r > n - r) r = n - r; // because C(n, r) == C(n, n - r) longlong ans = 1; int i; for(i = 1; i <= r; i++) { ans *= n - r + i; ans /= i; } return ans; }
# define MAX 100 // assuming we need first 100 rows longlong triangle[MAX + 1][MAX + 1];
voidmakeTriangle(){ int i, j;
// initialize the first row triangle[0][0] = 1; // C(0, 0) = 1
// 常见运算符 inline V operator * (constdouble &x,const V &a){return (V){a.x*x,a.y*x};} // 点积、叉积 |a|*|b| cos / sin(可代表面积) inlinedoubleoperator * (const V &a,const V &b){return a.x*b.x+a.y*b.y;} inlinedoubleoperator ^ (const V &a,const V &b){return a.x*b.y-a.y*b.x;}
// 相等 inlinebooloperator == (const V &a,const V &b){returnabs(a.x-b.x)<eps&&abs(a.y-b.y)<eps;} inlinebooloperator != (const V &a,const V &b){return !(a==b);}
// 长度 inlinedoublelen(const V &a){returnsqrt(a.x*a.x+a.y*a.y);}
// 角度 // 两向量与原点的夹角 inlinedoubleangle(const V &a,const V &b){ returnacos(a * b / len(a) / len(b)); }
// 钝角 inlinebooldun(const V &a,const V &b,const V &c){return ((b-a)*(c-a))<-eps;}//angle:BAC
// #define int long long #define ll long long #define vi vector<ll> #define vvi vector<vi> #define rep(i, a, b) for(auto i = (a); (i) < (b); (i)++) #define rrep(i, b, a) for (auto i = (b); (i) > (a); (i)--) #define fastio std::ios_base::sync_with_stdio(false); cin.tie(NULL); #define all(v) (v).begin(), (v).end() #define sz(v) (int)(v).size() #define ump unordered_map<ll, ll> #define pub push_back #define pob pop_back #define arr array<ll, 3> #define pii pair<ll, ll> #define fi first #define se second
unique/count/find/rotate
1 2 3 4 5 6 7 8 9
nums.erase(unique(nums.begin(), nums.end()), nums.end()); auto cnt = count(all(s),'1'); std::size_t found = str.find(str2); find(vec.begin(), vec.end(), item);
node* build(vi &a, int l, int r){ if (l > r) returnnullptr; node *head = newnode(a[l]); int ml = r + 1; rep (i, l + 1, r + 1) { if (a[i] > a[0]) { ml = i; break; } } head->left = build(a, l + 1, ml - 1); head->right = build(a, ml, r); return head; }
时间分析
总的合并次数 + 遍历次数
复杂度分析 - 随机变量的估计 ? random
200ms 3*n 三倍时间 == 超时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 10**9 #include<chrono> usingnamespace std::chrono; auto start = high_resolution_clock::now(); // 10**9 视为1s // ull 2s-6s(个人pc), oj 1-2s // 10**18 = 10**9s; 3600s = 1h ... for (ull i = 1; i <= a; i++) { res++; } cout << res << endl; auto stop = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function: " << duration.count() << " microseconds" << endl;