Uploaded by Ahnaf

trd

advertisement
Punjab University College of Information Technology
Renegades
Contents
1 Graphs
1.1 Eulerian circuit / path . . . . . . . .
1.2 Bridges . . . . . . . . . . . . . . . . .
1.3 Articulation/Cut Point . . . . . . . .
1.4 Strongly Connected Components .
1.5 Minimum Spanning Tree (Kruskal)
1.6 Bellman Ford . . . . . . . . . . . . .
1.7 Dijkstra . . . . . . . . . . . . . . . .
1.8 Floyd Warshall . . . . . . . . . . . .
1.8.1 Printing shortest paths . . .
1.8.2 Diameter of graph . . . . . .
1.9 Path counting . . . . . . . . . . . . .
1.10 Max Flow . . . . . . . . . . . . . . .
1.11 Min max cost flow . . . . . . . . . .
2 Data Structures
2.1 Strings . . . . . . . . . . . . . . . .
2.1.1 KMP . . . . . . . . . . . . .
2.1.2 Suffix Array (empty) . . .
2.2 Trees . . . . . . . . . . . . . . . . .
2.2.1 Lowest Common Ancestor
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
2
3
3
4
4
5
6
7
7
8
8
8
9
.
.
.
.
.
11
11
11
11
11
11
3 Dynamic Programming
12
3.1 Prefix 2d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2 Max Sum Sub-Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4 Number Theory
13
4.1 Modulo Inverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.2 Combinatorics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.3 lcm gcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5 Misc
13
5.1 RMQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.2 Matrix Exponentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
6 Python
14
1
1
Graphs
1.1
Eulerian circuit / path
An Eulerian Path is a path of edges that visits all the edges in a graph exactly once. Similarly, an Eulerian
circuit is an Eulerian path which starts and ends on the same vertex. Here are conditions.
Type
Undirected
Graph
Directed
Graph
Eulerian circuit
Every Vertex has an
even degree
Every Vertex has
equal indegree and
outdegree
Eulerian path
Either every Vertex has an even degree or exactly two
edges have odd degree
At most one vertex has outdegree - indegree = 1 and atmost one vertex has indegree - outdegree = 1 and all other
vertices have equal in and out degree
// to check for the direted graph
list<int> path;
bool pathExist(vector<int> in, vector<int> out, int n)
{
int startNodes = 0, endNodes = 0;
for (int i = 0; i < n; i++)
{
if (out[i] - in[i] > 1 || in[i] - out[i] > 1) return false;
else if (out[i] - in[i] == 1) startNodes++;
else if (in[i] - out[i] == 1) endNodes++;
}
return (endNodes == 0 && startNodes == 0) || (endNodes == 1 && startNodes == 1);
}
void DFS(vector< vector<int> >& adj_list, int curr, vector<int>& out)
{
while (out[curr]) DFS(adj_list, adj_list[curr][--out[curr]], out);
path.push_front(curr);
}
int findStartNode(vector<int> in, vector<int> out, int n)
{
int start = 0;
for (int i = 0; i < n ; i++)
{
// Unique starting node.
if (out[i] - in[i] == 1) return i;
// Start at a node with an outgoing edge.
if (out[i]) start = i;
}
return start;
}
void EulerPath(vector< vector<int> >& adj_list, int curr)
{
vector<int> out(adj_list.size(), 0), in(adj_list.size(), 0);
for (int u = 0; u < adj_list.size(); u++)
for (auto v : adj_list[u])
{
2
out[u]++;
in[v]++;
}
if (!pathExist(in, out, adj_list.size())) return;
int s = findStartNode(in, out, adj_list.size());
DFS(adj_list, s, out);
}
1.2
Bridges
Informally, the problem is formulated as follows: given a map of cities connected with roads, find all
"important" roads, i.e. roads which, when removed, cause disappearance of a path between some pair of
cities.
int n, timer; // number of nodes
vector <int> visited(n, false);
vecotr <vector<int> > adj(n, vector<int>());
vector<int> tin(n), low(n);
void dfs(int v, int p) {
visited[v] = true;
tin[v] = low[v] = ++timer;
for (int u : adj[v])
if (u == p) continue; // direct edge to parent
else if (visited[u]) // back edge
low[v] = min(low[v], tin[u]);
else { // forward edge
dfs(u, v);
low[v] = min(low[v], low[u]);
if (low[u] > tin[v]) // bridge found
process_the_bridge(v, u); // your logic
}
}
int find_bridges() {
for (int i = 0; i < n; i++) if (!visited[i]) dfs (i, -1);
}
1.3
Articulation/Cut Point
int n, timer;
vector <int> visited(n, false);
vecotr <vector<int> > adj(n, vector<int>());
vector<int> tin(n), low(n);
void dfs(int v, int p) {
visited[v] = true;
tin[v] = in[v] = ++timer;
int children = 0;
for (int u : adj[v])
if (u == p) continue;
else if (visited[u]) low[v] = min(low[v], tin[u]);
3
else {
dfs(u, v); children++;
low[v] = min(low[v], low[u])
if (low[u] >= tin[v] and p != 1) // excluding root
process_the_cutpoint(v);
}
if (p == -1 and children > 1)
process_the_cutpoint(v);
}
void find_cutpoints() {
for (int i = 0; i < n; i++) if (!visited[i]) dfs(i, -1);
}
1.4
Strongly Connected Components
const int n = 7;
stack<int> s;
bool onStack[n] = {0};
bool visited[n] = {0};
int timer, sccCount;
int tin[n], low[n];
vector <vector<int>> adj_list(n);
void dfs(int v) {
// Do some book keeping stuff
visited[v] = true;
s.push(v);
onStack[v] = true;
tin[v] = low[v] = ++timer;
for (int u : adj_list[v]) {
if (!visited[u]) dfs(u);
if (onStack[u]) low[v] = min(low[v], low[u]);
}
// after exploring all the adjacent nodes of v
if (tin[v] == low[v]) { // we are at the start of scc, empty the stack till the start of the s
int u;
while (1) {
u = s.top(); s.pop();
onStack[u] = false;
low[u] = tin[v];
printf("%d ", u);
if (u == v) {
puts(""); break;
}
}
sccCount++;
}
}
void tarjan_scc() {
for (int i = 0; i < n; i++)
if (!visited[i]) dfs(i);}
1.5
Minimum Spanning Tree (Kruskal)
4
const int MAX = 1e4 + 5;
int id[MAX], nodes, edges;
pair <long long, pair<int, int> > p[MAX];
void initialize() {
for (int i = 0; i < MAX; ++i)
id[i] = i;
}
int root(int x) {
while (id[x] != x)
{
id[x] = id[id[x]];
x = id[x];
}
return x;
}
void union1(int x, int y) {
int p = root(x);
int q = root(y);
id[p] = id[q];
}
long long kruskal(pair<long long, pair<int, int> > p[]) {
int x, y;
long long cost, minimumCost = 0;
sort(p, p + edges);
for (int i = 0; i < edges; ++i) {
// Selecting edges one by one in increasing order from the beginning
x = p[i].second.first;
y = p[i].second.second;
cost = p[i].first;
if (root(x) != root(y)) // Check if the selected edge is creating a cycle or not
{
minimumCost += cost;
union1(x, y);
}
}
return minimumCost;
}
1.6
Bellman Ford
struct edge {
int a, b, cost;
};
int n, m, v;
vector<edge> e;
const int INF = 1000000000;
void solve() {
vector<int> d (n, INF);
5
d[v] = 0;
vector<int> p (n - 1);
int x;
for (int i = 0; i < n; ++i) {
x = -1;
for (int j = 0; j < m; ++j)
if (d[e[j].a] < INF)
if (d[e[j].b] > d[e[j].a] + e[j].cost) {
d[e[j].b] = max (-INF, d[e[j].a] + e[j].cost);
p[e[j].b] = e[j].a;
x = e[j].b;
}
if (x == -1) break;
}
if (x == -1) cout << "No negative cycle from " << v;
else {
int y = x;
for (int i = 0; i < n; ++i)
y = p[y];
vector<int> path;
for (int cur = y ;; cur = p[cur]) {
path.push_back (cur);
if (cur == y && path.size() > 1) break;
}
reverse (path.begin(), path.end());
cout << "Negative cycle: ";
for (int i = 0; i < path.size(); ++i) cout << path[i] << ’ ’;
}
}
1.7
Dijkstra
vector <vector< pii >> adj_list(maxNodes);
vector <vector<int> > dijkstra(int source) {
vector <int> d(maxNodes, 99999), p(maxNodes);
vector <bool> done(maxNodes, false);
p[source] = source;
d[source] = 0;
priority_queue <pii, vector<pii>, greater<pii>> pq;
pq.push({0, source});
while(!pq.empty()){
int curr, len, to;
curr = pq.top().second; pq.pop();
if (done[curr]) continue;
done[curr] = true;
for (auto edge: adj_list[curr]){
tie(to, len) = edge;
if (d[curr] + len < d[to]){
d[to] = d[curr] + len;
6
p[to] = curr;
pq.push({d[to], to});
}
}
}
return {d, p};
}
void printPath(vector<int>& p, int s){
if (p[s] == s) printf ("%d ---> ", s);
else printPath(p, p[s]), printf ("%d ---> ", s);
}
int main(){
auto ans = dijkstra(2);
for (auto d: ans[0])
cout << d << ’ ’;
puts("");
for (int i=0; i<maxNodes; i++) if(ans[0][i] != 99999) printPath(ans[1], i), puts(" END");
return 0;
}
1.8
Floyd Warshall
for (int k = 0; k < n; ++k)
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (d[i][k] < INF && d[k][j] < INF)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
// It is assumed that if there is no edge between any two vertices i and j,
// then the matrix at d[i][j] contains a large number (large enough so that
// it is greater than the length of any path in this graph).
1.8.1
Printing shortest paths
// let p be a 2D parent matrix, where p[i][j] is the last vertex before j
// on a shortest path from i to j, i.e. i -> ... -> p[i][j] -> j
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
p[i][j] = i; // initialize the parent matrix
for (int k = 0; k < V; k++)
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++) // this time, we need to use if statement
if (AdjMat[i][k] + AdjMat[k][j] < AdjMat[i][j]) {
AdjMat[i][j] = AdjMat[i][k] + AdjMat[k][j];
p[i][j] = p[k][j]; // update the parent matrix
}
// when we need to print the shortest paths, we can call the method below:
void printPath(int i, int j) {
if (i != j) printPath(i, p[i][j]);
printf(" %d", j);
}
7
1.8.2
Diameter of graph
The diameter of a graph is defined as the maximum shortest path distance between any pair of vertices of
that graph. To find the diameter of a graph, we first find the shortest path between each pair of vertices
(i.e. the APSP problem). The maximum distance found is the diameter of the graph. However, we can only
do this for a small graph with V <= 400.
1.9
Path counting
vector<bool> visited(6, false);
vector<int> dp(6, 0);
vector <vector<int>> adj_list(6);
int count_path(int v, int t) {
if (v == t) return 1;
if (dp[v]) return dp[v];
visited[v] = true;
for (auto u : adj_list[v])
if (!visited[u]) dp[v] += count_path(u, t);
visited[v] = false;
return dp[v];
}
vector <int> order;
void topological_sort(int v) {
visited[v] = true;
for (auto u : adj_list[v]) if (!visited[u]) topological_sort(u);
order.push_back(v);
}
int solve(int v, int t) {
order.clear();
visited.assign(6, false);
topological_sort(v);
reverse(order.begin(), order.end());
vector<int> dp(6, 0);
dp[v] = 1;
for (auto u : order)
for (auto w : adj_list[u])
dp[w] += dp[u];
return dp[t];
}
1.10
Max Flow
#define vi vector<int>
int n;
vector<vi> capacity, adj_list;
8
int bfs(int s, int t, vi& parent){
fill(parent.begin(), parent.end(), -1);
parent[s] = -2;
queue< pair<int, int> > q;
q.push({s, inf});
int cur, flow;
while(!q.empty()){
tie(cur, flow) = q.front();
q.pop();
for (auto nxt : adj_list[curr])
if (parent[nxt] == -1 and capacity[cur][next]){
parent[nxt] = cur;
int new_flow = min(flow, capacity[cur][nxt];
if (nxt == t) return new_flow;
q.push({nxt, new_flow});
}
}
return 0;
}
int max_flow(int s, int t) {
int flow = 0, new_flow;
vi parent(n);
while(new_flow = bfs(s, t, parent)){
flow += new_flow;
int cur = t;
while(cur != s){
int prev = parent[cur];
capacity[prev][cur] -= new_flow;
capacity[cur][prev] += new_flow;
cur = prev;
}
}
return flow;
}
1.11
Min max cost flow
const ll INF = numeric_limits<ll>::max() / 4;
typedef vector<ll> VL;
struct MCMF {
int N;
vector<vi> ed, red;
vector<VL> cap, flow, cost;
vi seen;
VL dist, pi;
vector<pii> par;
MCMF(int N) :
N(N), ed(N), red(N), cap(N, VL(N)), flow(cap), cost(cap),
seen(N), dist(N), pi(N), par(N) {}
9
void addEdge(int from, int to, ll cap, ll cost) {
this->cap[from][to] = cap;
this->cost[from][to] = cost;
ed[from].push_back(to);
red[to].push_back(from);
}
void path(int s) {
fill(all(seen), 0);
fill(all(dist), INF);
dist[s] = 0; ll di;
__gnu_pbds::priority_queue<pair<ll, int>> q;
vector<decltype(q)::point_iterator> its(N);
q.push({0, s});
auto relax = [&](int i, ll cap, ll cost, int dir) {
ll val = di - pi[i] + cost;
if (cap && val < dist[i]) {
dist[i] = val;
par[i] = {s, dir};
if (its[i] == q.end()) its[i] = q.push({ -dist[i], i});
else q.modify(its[i], { -dist[i], i});
}
};
while (!q.empty()) {
s = q.top().second; q.pop();
seen[s] = 1; di = dist[s] + pi[s];
for (int i : ed[s]) if (!seen[i]) relax(i, cap[s][i] - flow[s][i], cost[s][i], 1);
for (int i : red[s]) if (!seen[i]) relax(i, flow[i][s], -cost[i][s], 0);
}
rep(i, 0, N) pi[i] = min(pi[i] + dist[i], INF);
}
pair<ll, ll> maxflow(int s, int t) {
ll totflow = 0, totcost = 0;
while (path(s), seen[t]) {
ll fl = INF;
for (int p, r, x = t; tie(p, r) = par[x], x != s; x = p)
fl = min(fl, r ? cap[p][x] - flow[p][x] : flow[x][p]);
totflow += fl;
for (int p, r, x = t; tie(p, r) = par[x], x != s; x = p)
if (r) flow[p][x] += fl;
else flow[x][p] -= fl;
}
rep(i, 0, N) rep(j, 0, N) totcost += cost[i][j] * flow[i][j];
return {totflow, totcost};
}
// If some costs can be negative, call this before maxflow:
void setpi(int s) { // (otherwise, leave this out)
fill(all(pi), INF); pi[s] = 0;
int it = N, ch = 1; ll v;
10
while (ch-- && it--)
rep(i, 0, N) if (pi[i] != INF)
for (int to : ed[i]) if (cap[i][to])
if ((v = pi[i] + cost[i][to]) < pi[to])
pi[to] = v, ch = 1;
assert(it >= 0); // negative cost cycle
}
};
2
Data Structures
2.1
Strings
2.1.1
KMP
vector<int> prefix_kmp(string word, string sentence)
{
int n = sentence.size();
vector<int> pi(n, 0);
for (int i = 0; i < n; i++)
{
int j = pi[i - 1];
while (j > 0 and word[i] != sentence[j] and j >= word.size())
j = pi[j - 1];
pi[i] = j + (word[i] == sentence[j]);
}
return pi;
}
2.1.2
2.2
Suffix Array (empty)
Trees
2.2.1
Lowest Common Ancestor
class TreeAncestor {
public:
int log = 20;
vector<int> depth;
vector < vector<int> > table;
void dfs(int curr, vector < vector<int> >& adj_list) {
for (int i=1; i<=log; i++)
table[curr][i] = table[table[curr][i-1]][i-1];
// update children depth and move on to them
for (auto v : adj_list[curr]){
depth[v] = depth[curr] + 1;
table[v][0] = curr;
dfs(v, adj_list);
}
}
TreeAncestor(int n, vector<int>& parent) {
depth = vector<int>(n+1);
table = vector<vector<int>>(n+1, vector<int>(log+1));
11
vector < vector<int> > adj_list(n+1);
int root;
for (int i=0; i<parent.size(); i++)
if (parent[i] == -1) root = i;
else adj_list[parent[i]].push_back(i);
depth[root] = 0;
dfs(root, adj_list);
}
int getKthAncestor(int node, int k) {
if (depth[node] < k) return -1;
for (int i = 0; i <= log; i++) if (k & (1 << i))
node = table[node][i];
return node;
}
int getLCA(int a, int b){
if(depth[a] < depth[b]) swap(a, b); // make ’a’ the deeper node
int k = depth[a] - depth[b];
a = getKthAncestor(a, k);
// get same depth
if (a==b) { return a; }
// if b was same is an ancestor of a
// moove both a and b with powers of 2 (below any commone ancesstor)
for (int i=log-1; i>=0; i--)
if (up[a][i] != up[b][i]){
a = up[a][i];
b = up[b][i];
}
return up[a][0];
}
};
3
3.1
Dynamic Programming
Prefix 2d
// prefix sum
REP(i, n) REP(j, m)
prefix[i + 1][j + 1] = prefix[i + 1][j + 1] + prefix[i][j + 1] + prefix[i + 1][j] - prefix[i][j];
int ans = prefix[A][B] + prefix[a - 1][b - 1] - prefix[A][b - 1] - prefix[a - 1][B]
3.2
Max Sum Sub-Rectangle
int n, grid[101][101];
int maxSubArraySum(int* arr) {
int ans = INT_MIN, a = 0;
for (int i = 0; i < n; i++) {
a += arr[i];
ans = max(ans, a);
a = max(a, 0);
}
return ans;
12
}
int main() {
int rectSum, maxRectSum = INT_MIN;
for (int l = 0; l < n; l++) {
int runningArray[n] = {0};
for (int r = l; r < n; r++) {
for (int i = 0; i < n; i++)
runningArray[i] += grid[i][r];
rectSum = maxSubArraySum(runningArray);
maxRectSum = max(rectSum, maxRectSum);
}
}
printf("%d\n", maxRectSum);
}
return 0;
}
4
4.1
Number Theory
Modulo Inverse
ll moduloInverse(ll base, ll p, ll mod) {
ll identity = 1LL;
while (p > 1) {
if (p & 1) identity = (identity * 1LL * base) % mod;
base = (base * 1LL * base) % mod;
p /= 2;
}
return (identity * base * 1LL) % mod;
}
4.2
4.3
Combinatorics
Pn
k = n( n + 1)/2
Pkn=0 2
k = n( n + 1)(2 n + 1)/6
¢
Pkn=0 4 ¡ 5
k = ¡6 n + 15¢n4 + 10 n3 − n /30
k
=
0
Pn
x k = x n+1 − 1 /( x − 1)
k=0
Pb
k = (a + b)( b − a + 1)/2
Pkn=a 3
k = n2 ( n + 1)2 /4
¢
Pkn=0 5 ¡ 6
k = 2¡n + 6 n5 + 5 n4 − n2 /12¢
k
=
0
Pn
kx k = x − ( n + 1) x n+1 + nx n+2 /( x − 1)2
k=0
lcm gcd
ll gcd(ll a,ll b){
if(b==0) return a;
else return gcd(b,a%b);
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
5
5.1
Misc
RMQ
13
#define better(a,b) A[a]<A[b]?(a):(b)
int make_dp(int n) { // N log N
REP(i,n) H[i][0]=i;
for(int l=0,k; (k=1<<l) < n; l++) for(int i=0;i+k<n;i++)
H[i][l+1] = better(H[i][l], H[i+k][l]);
}
int query_dp(int a, int b) {
int l = __lg(b-a);
return better(H[a][l], H[b-(1<<l)+1][l]);
}
5.2
Matrix Exponentation
template<class T>
class Matrix{
public:
vector< vector<T> > mat; // the contents of matrix as a 2D-vector
int n_rows, n_cols; // number of rows and columns
Matrix(vector< vector<T> > values)
: mat(values), n_rows(values.size()), n_cols(values[0].size()) {}
static Matrix identity_matrix(int n){
vector< vector<T> > values(n, vector<T>(n, 0));
for(int i = 0; i < n; i++)
values[i][i] = 1;
return values;
}
Matrix operator*(const Matrix<T> &other) const {
int n = n_rows, m = other.n_cols;
vector< vector<T> > result(n_rows, vector<T>(m, 0));
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
for(int k = 0; k < n_cols; k++)
{
result[i][j] = (result[i][j] + mat[i][k] * other.mat[k][j]) % mod;
(result[i][j] += mod) %= mod;
}
return Matrix(result);
}
};
Matrix<long long> M({
{1, 1},
{1, 0}
});
auto ans = fast_exponentiation(M, n-1);
cout << ans.mat[0][0] << ’\n’;
6
Python
import itertools
14
stuff = [1, 2, 3]
for L in range(len(stuff) + 1):
for subset in itertools.combinations(stuff, L):
print(list(subset))
def dfs(g, i):
stack = [i]
visited = set()
while stack:
start = stack[-1]
if start not in visited:
visited.add(start)
for child in g[start]:
stack.append(child)
else:
stack.pop()
def isBipartite(g):
col = [-1]*(len(g))
q = []
for i in range(len(g)):
if (col[i] == -1):
q.append([i, 0])
col[i] = 0
while len(q) != 0:
p = q[0]
q.pop(0)
v = p[0]
c = p[1]
for j in g[v]:
if (col[j] == c):
return False
if (col[j] == -1):
if c == 1:
col[j] = 0
else:
col[j] = 1
q.append([j, col[j]])
return True
g = [[1, 2], [0], [0, 3], [2]]
print(isBipartite(g))
def bipartiteMatch(graph):
matching = {}
for u in graph:
for v in graph[u]:
if v not in matching:
matching[v] = u
break
while 1:
preds = {}
unmatched = []
pred = dict([(u,unmatched) for u in graph])
for v in matching:
del pred[matching[v]]
15
layer = list(pred)
while layer and not unmatched:
newLayer = {}
for u in layer:
for v in graph[u]:
if v not in preds:
newLayer.setdefault(v,[]).append(u)
layer = []
for v in newLayer:
preds[v] = newLayer[v]
if v in matching:
layer.append(matching[v])
pred[matching[v]] = v
else:
unmatched.append(v)
if not unmatched:
unlayered = {}
for u in graph:
for v in graph[u]:
if v not in preds:
unlayered[v] = None
return (matching,list(pred),list(unlayered))
def recurse(v):
if v in preds:
L = preds[v]
del preds[v]
for u in L:
if u in pred:
pu = pred[u]
del pred[u]
if pu is unmatched or recurse(pu):
matching[v] = u
return 1
return 0
for v in unmatched: recurse(v)
def min_vertex_cover(left_v, right_v):
data_hk = bipartiteMatch(left_v)
print(data_hk)
left_mis = data_hk[1]
right_mis = data_hk[2]
mvc = left_v.copy()
mvc.update(right_v)
for v in left_mis:
del(mvc[v])
for v in right_mis:
del(mvc[v])
return mvc
leftv = {’a’: [1, 3], ’c’: [1, 3], ’d’: [3, 6], ’h’: [8], ’i’: [8]}
rightv = {1: [’a’, ’c’], 3: [’a’, ’c’, ’d’], 6: [’d’], 8: [’h’, ’i’]}
print(min_vertex_cover(leftv, rightv))
def
make_set : # disjoint set
for v in range(n + 1):
parent[v] = v
16
size[v] = 1
def find_set(v):
if (v == parent[v]): return v
parent[v] = find_set(parent[v])
return parent[v]
def union_sets(a, b):
a = find_set(a)
b = find_set(b)
if (a != b):
if (size[a] < size[b]):
a, b = b, a
parent[b] = a
size[a] += size[b]
n, parent, size = 5, [None] * (n + 1), [None] * (n + 1)
make_set(n)
def rotate_a_matrix(a) :
n = len(a)
for r in range(n//2):
for c in range(r, n - r - 1):
a[r][c], a[c][n-1-r], a[n-1-r][n-1-c], a[n-1-c][r] = a[n-1-c][r], a[r][c], a[c]
a[r][c], a[c][n-1-r], a[n-1-r][n-1-c], a[n-1-c][r] = a[c][n-1-r], a[n-1-r][n-1def kadane(arr, start, finish, n): # Largest sum submatrix
Sum = 0
maxSum = -999999999999
i = None
finish[0] = -1
local_start = 0
for i in range(n):
Sum += arr[i]
if Sum < 0:
Sum = 0
local_start = i + 1
elif Sum > maxSum:
maxSum = Sum
start[0] = local_start
finish[0] = i
if finish[0] != -1:
return maxSum
maxSum = arr[0]
start[0] = finish[0] = 0
for i in range(1, n):
if arr[i] > maxSum:
maxSum = arr[i]
start[0] = finish[0] = i
return maxSum
def findMaxSum(M):
global ROW, COL
maxSum, finalLeft = -999999999999, None
finalRight, finalTop, finalBottom = None, None, None
left, right, i = None, None, None
temp = [None] * ROW
Sum = 0
17
start = [0]
finish = [0]
for left in range(COL):
temp = [0] * ROW
for right in range(left, COL):
for i in range(ROW):
temp[i] += M[i][right]
Sum = kadane(temp, start, finish, ROW)
if Sum > maxSum:
maxSum = Sum
finalLeft = left
finalRight = right
finalTop = start[0]
finalBottom = finish[0]
print("(Top, Left)", "(", finalTop,
finalLeft, ")")
print("(Bottom, Right)", "(", finalBottom,
finalRight, ")")
print("Max sum is:", maxSum)
ROW = 4
COL = 5
M = [[1, 2, -1, -4, -20],
[-8, -3, 4, 2, 1],
[3, 8, 10, 1, 3],
[-4, -1, 1, 7, -6]]
n = rows = 10 # Flood Fill
m = columns = 10
a = [] # input array
q = []
four = [(1, 0), (-1, 0), (0, 1), (0, -1)]
eight = [(-1, -1), (-1, 0), (-1, 1),(0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
for i in range(1, n):
for j in range(1, m):
if a[i][j] == ’.’:
q.append((i, j))
while q:
x, y = q.pop()
a[x][y] = ’#’
for dx, dy in four:
if a[x + dx][y + dy] == ’.’:
q.append((x + dx, y + dy))
def fastSieve(n):
r = [False, True] * (n//2) + [True]
r[1], r[2] = False, True
for i in range(3, int(1 + n**0.5), 2):
if r[i]:
r[i*i::2*i] = [False] * ((n+2*i-1-i*i)//(2*i))
return r
def factors(n):
return list(set(reduce(list._add_,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0))))
18
from math import inf # segment tree
n, k = map(int, input().split())
a = list(map(int, input().split()))
t = [inf] * (4 * n)
# initial array, current vertex(1), array left(0), array right(n - 1)
def build(a, v, tl, tr):
if tl == tr:
t[v] = a[tl]
else:
tm = (tl + tr) // 2
build(a, v * 2, tl, tm)
build(a, v * 2 + 1, tm + 1, tr)
t[v] = min(t[v * 2], t[v * 2 + 1])
# current vertex(1), array left(0), array right(n - 1), query left, query right (0 indexed)
def query(v, tl, tr, l, r):
if l > r:
return inf
if l == tl and r == tr:
return t[v]
tm = (tl + tr) // 2
return min(query(v * 2, tl, tm, l, min(r, tm)), query(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r))
# current vertex(1), array left(0), array right(n - 1), position (0 indexed), new value
def update(v, tl, tr, pos, new_val):
if tl == tr:
t[v] = new_val
else:
tm = (tl + tr) // 2
if pos <= tm:
update(v * 2, tl, tm, pos, new_val)
else:
update(v * 2 + 1, tm + 1, tr, pos, new_val)
t[v] = min(t[v * 2], t[v * 2 + 1])
build(a, 1, 0, n - 1)
n = int(input()) # count subarrays with xor
a = list(map(int, input().split()))
sq=[]
p=0
while p*p<=4*10**5:
sq.append(p*p)
p+=1
occ = [0] * (2 * n) # number of times each element occured in the xor prefix array
occ[0] = 1
# 0 obviously occured 1 times already if we take empty subarray
c = 0 # count for subarrays with xor equal to any value is sq
x = 0 # prefix xor uptill i
for i in range(n):
x ^= a[i]
for j in sq:
if j ^ x < 2 * n:
c += (occ[j ^ x])
occ[x] += 1
print(c)
from bisect import bisect_left # Longest increasing subsequence in nlgn
19
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
ans = [nums[0]]
for i in range(1, len(nums)):
if nums[i] > ans[-1]:
ans.append(nums[i])
else:
ind = bisect_left(ans, nums[i])
ans[ind] = nums[i]
return len(ans)
print((999999).bit_length()) # find number of bits required to store an integer
print(format(8, ’018b’)) # convert decimal to binary
def ConvertDecimalToBaseX(num, x):
if num == 0:
return [0]
digits = []
while num:
digits.append(int(num % x))
num //= x
return digits[::-1]
def ConvertBaseXToDecimal(num, CurrBase):
ans = 0
for i in map(int, num):
ans = CurrBase * ans + i
return ans
def is_square(apositiveint):
x = apositiveint // 2
seen = set([x])
while x * x != apositiveint:
x = (x + (apositiveint // x)) // 2
if x in seen: return False
seen.add(x)
return True
20
Download