├── tcr.pdf ├── chinese.png ├── Kitlogo_en_cmyk.pdf ├── arithmetik ├── .DS_Store ├── ikj.cpp ├── potenz.cpp ├── simpson.cpp ├── romberg.cpp ├── lr.cpp ├── bigint.java ├── gauss.cpp ├── fft.cpp ├── gauss2.cpp └── bigint.cpp ├── formulae ├── chinese.png ├── Formulae.pdf ├── Formulae.aux ├── Formulae.log └── Formulae.tex ├── .gitmodules ├── Formulae_gametheory_hackenbush_colon.jpg ├── Formulae_gametheory_hackenbush_graph_example.jpg ├── Formulae_gametheory_hackenbush_graph_fusion.jpg ├── .gitignore ├── Makefile ├── dp.tex ├── geometrie ├── old │ ├── header.cpp │ ├── kreis.cpp │ ├── bresenham.cpp │ ├── poly-punkt.cpp │ ├── gerade.cpp │ ├── graham.cpp │ ├── dreieck.cpp │ └── clip.cpp ├── Kernel.cpp ├── _Modul_Farthestpoints_Graham.cpp └── 3DConvexHull.cpp ├── rekurrenzen ├── lis.cpp └── subset-sum.cpp ├── template.java ├── graphentheorie ├── eulerkreis.cpp ├── kruskal.cpp ├── prim.cpp ├── topo-sort.cpp ├── BipartiteMatching2.cpp ├── Maxflow_EK.cpp ├── dijkstra2.cpp ├── bi-match.cpp ├── Maxflow_CS.cpp ├── scc_old.cpp ├── bellman-ford.cpp ├── floyd-warshall.cpp ├── dijkstra.cpp ├── stoer-wagner.cpp ├── arti-bruecken.cpp ├── BipartiteMatching.cpp ├── ford-fulkerson.cpp ├── scc.cpp ├── Maxflow_Dinic.cpp ├── lca_Tarjan.cpp ├── mincostmaxflow.cpp ├── MincostFlow_SPFA.cpp └── Cutnode&Bridge.cpp ├── suchen └── select.cpp ├── datenstrukturen ├── heap.cpp ├── stl_rank_select.cpp ├── SkewHeap.cpp ├── disjoint.cpp ├── trie-array.cpp ├── trie-list.cpp ├── rmq.cpp ├── range_tree.cpp ├── avl.cpp ├── Segment_tree.cpp └── splay.cpp ├── stringology ├── kmp.cpp ├── Hashing.cpp ├── Z_Algorithm.cpp ├── Manacher.cpp └── suffixarray.cpp ├── zahlentheorie ├── phi.cpp ├── erathostenes.cpp ├── miller-rabin.cpp ├── euclid.cpp ├── BinomialModK.cpp └── NumberTheory.cpp ├── stringology.tex ├── parser ├── arith-eval.cpp ├── cyk.cpp └── infix-postfix.cpp ├── template.cpp ├── parser.tex ├── suchen.tex ├── datenstrukturen.tex ├── zahlentheorie.tex ├── geometrie.tex ├── graphentheorie.tex ├── tcr.tex ├── arithmetik.tex ├── rekurrenzen.tex ├── Formulae_gametheory.tex └── formulae.tex /tcr.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/tcr.pdf -------------------------------------------------------------------------------- /chinese.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/chinese.png -------------------------------------------------------------------------------- /Kitlogo_en_cmyk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/Kitlogo_en_cmyk.pdf -------------------------------------------------------------------------------- /arithmetik/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/arithmetik/.DS_Store -------------------------------------------------------------------------------- /formulae/chinese.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/formulae/chinese.png -------------------------------------------------------------------------------- /formulae/Formulae.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/formulae/Formulae.pdf -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "niklas"] 2 | path = niklas 3 | url = https://github.com/niklasb/contest-algos 4 | -------------------------------------------------------------------------------- /Formulae_gametheory_hackenbush_colon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/Formulae_gametheory_hackenbush_colon.jpg -------------------------------------------------------------------------------- /Formulae_gametheory_hackenbush_graph_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/Formulae_gametheory_hackenbush_graph_example.jpg -------------------------------------------------------------------------------- /Formulae_gametheory_hackenbush_graph_fusion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niklasb/tcr/HEAD/Formulae_gametheory_hackenbush_graph_fusion.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.aux 3 | *.log 4 | *.backup 5 | *.bak 6 | *.out 7 | *.bbl 8 | *.blg 9 | *.brf 10 | *.idx 11 | *.ilg 12 | *.ind 13 | *.toc 14 | *.fls 15 | -------------------------------------------------------------------------------- /arithmetik/ikj.cpp: -------------------------------------------------------------------------------- 1 | for(i = 0; i < SIZE; i++) 2 | for(k = 0; k < SIZE; k++) 3 | for(j = 0; j < SIZE; j++) 4 | c[i][j] += a[i][k] * b[k][j]; 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | pdflatex tcr.tex 3 | pdflatex tcr.tex 4 | make clean 5 | clean: 6 | rm -f *~ .*~ *.aux *.log *.backup *.out *.backup *.bbl *.blg *.brf *.idx *.ilg *.ind *.toc *.fls 7 | -------------------------------------------------------------------------------- /arithmetik/potenz.cpp: -------------------------------------------------------------------------------- 1 | int fast_exp(int a, int b) { 2 | int r = 1; 3 | 4 | while (b > 0) { 5 | if ((b & 1)) r *= a; 6 | b >>= 1; 7 | a *= a; 8 | } 9 | 10 | return r; 11 | } 12 | -------------------------------------------------------------------------------- /dp.tex: -------------------------------------------------------------------------------- 1 | \section{DP optimization} 2 | 3 | \subsection{Convex hull (monotonic insert)} 4 | \lstinputlisting{niklas/convex_hull/descasc.cpp} 5 | 6 | \subsection{Dynamic convex hull} 7 | \lstinputlisting{niklas/convex_hull/dynamic.cpp} 8 | 9 | -------------------------------------------------------------------------------- /geometrie/old/header.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const double PI = 2 * acos(0), EPS = 1e-9; 8 | 9 | typedef valarray vec; 10 | typedef valarray vecvec; 11 | -------------------------------------------------------------------------------- /formulae/Formulae.aux: -------------------------------------------------------------------------------- 1 | \relax 2 | \@writefile{toc}{\contentsline {section}{\numberline {1}Combinatorics}{1}} 3 | \@writefile{toc}{\contentsline {section}{\numberline {2}Number Theory}{2}} 4 | \@writefile{toc}{\contentsline {section}{\numberline {3}Probability}{2}} 5 | -------------------------------------------------------------------------------- /rekurrenzen/lis.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int eingabe[SIZE]; 4 | int seq[SIZE]; 5 | 6 | int lis() { 7 | int m = 0; 8 | for(int i = 0; i < p; ++i) { 9 | int j = lower_bound(seq, seq + m, eingabe[i]) - seq; 10 | if(j == m) seq[m++] = eingabe[i]; else seq[j] = eingabe[i]; 11 | } 12 | return m; 13 | } 14 | -------------------------------------------------------------------------------- /template.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | import java.math.*; 4 | public class Main { 5 | int n, m; 6 | public void run(Scanner in) throws Exception { 7 | n = in.nextInt(); 8 | System.out.println("foo"); 9 | } 10 | public static void main(String[] args) throws Exception { 11 | new Main().run(new Scanner(System.in)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /graphentheorie/eulerkreis.cpp: -------------------------------------------------------------------------------- 1 | list< int > cyc; 2 | void euler( list< int >::iterator i, int u ) { 3 | for( int v = 0; v < n; v++ ) if( graph[u][v] ) { 4 | graph[u][v] = graph[v][u] = false; 5 | euler( cyc.insert( i, u ), v ); 6 | } 7 | } 8 | 9 | int main() { 10 | // read graph into graph[][] and set n to the number of vertices 11 | euler( cyc.begin(), 0 ); 12 | // cyc contains an euler cycle starting at 0 13 | } 14 | -------------------------------------------------------------------------------- /suchen/select.cpp: -------------------------------------------------------------------------------- 1 | // Laufzeit in O(b - a) garantiert, sonst wie std::nth_element 2 | int select(int* a, int* b, int n) { 3 | if (b - a < 10000) { nth_element(a, a + n, b); return a[n]; } 4 | int* q = a; 5 | for (int *p = a; b - p >= 5; p += 5) { nth_element(p, p + 2, p + 5); swap(*q++, p[2]); } 6 | q = partition(a, b, bind2nd(less(), select(a, q, (q - a) / 2))); 7 | return n < q - a ? select(a, q, n) : select(q, b, n - (q - a)); 8 | } 9 | -------------------------------------------------------------------------------- /arithmetik/simpson.cpp: -------------------------------------------------------------------------------- 1 | double f(double x) { return exp(-x*x); } 2 | const double eps=1e-12; 3 | 4 | double simps(double a, double b) { // for ~4x less f() calls, pass fa,fm,fb around 5 | return (f(a) + 4*f((a+b)/2) + f(b))*(b-a)/6; 6 | } 7 | double integrate(double a, double b) { 8 | double m = (a+b)/2; 9 | double l = simps(a,m),r = simps(m,b),tot=simps(a,b); 10 | if (fabs(l+r-tot) < eps) return tot; 11 | return integrate(a,m) + integrate(m,b); 12 | } 13 | -------------------------------------------------------------------------------- /datenstrukturen/heap.cpp: -------------------------------------------------------------------------------- 1 | // hier mit int, aber es reicht, wenn operator< definiert ist 2 | void lift(vector& v, int i) { 3 | for (int j; i > 0; i = j) { 4 | j = (i - 1) / 2; 5 | if (!(v[j] < v[i])) break; 6 | swap(v[i], v[j]); 7 | } 8 | } 9 | void sink(vector& v, int i) { 10 | for (int j; (j = 2 * i + 1) < int(v.size()); i = j) { 11 | if (j + 1 < int(v.size()) && v[j] < v[j + 1]) ++j; 12 | if (!(v[i] < v[j])) break; 13 | swap(v[i], v[j]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /stringology/kmp.cpp: -------------------------------------------------------------------------------- 1 | int KMP(const string &s, const string &t) { 2 | static int next[10010]; int times = 0; 3 | next[0]=-1; 4 | for (int i = 1, tp = -1, lt = t.size(); i 2 | #include 3 | #include 4 | using namespace std; using namespace __gnu_pbds; 5 | typedef tree, rb_tree_tag, tree_order_statistics_node_update> Tree; 6 | int main() { 7 | Tree X; 8 | for (int i = 1; i <= 16; i <<= 1) X.insert(i); // { 1, 2, 4, 8, 16 }; 9 | cout << *X.find_by_order(3) << endl; // => 8 10 | cout << X.order_of_key(10) << endl; // => 4 = successor of 10 = min i such that X[i] >= 10 11 | } 12 | -------------------------------------------------------------------------------- /zahlentheorie/phi.cpp: -------------------------------------------------------------------------------- 1 | unsigned prime[NUM_PRIMES], phi[MAX]; 2 | bool used[NUM_PRIMES]; 3 | // Primzahlen muessen in prime stehen, Aufruf mit genphi(0, 1, 1) 4 | void genphi(unsigned next, unsigned n, unsigned p) { 5 | phi[n] = p; 6 | while (next < primes && n <= MAX / prime[next]) { 7 | if (!used[next]) { 8 | used[next] = true; 9 | genphi(next, n * prime[next], p * (prime[next] - 1)); 10 | used[next] = false; 11 | } else genphi(next, n * prime[next], p * prime[next]); 12 | ++next; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /zahlentheorie/erathostenes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned *sieve(unsigned *next, unsigned high) { 4 | unsigned char isprime[(high >> 4) + 1]; 5 | unsigned i, j; 6 | 7 | memset(isprime, 0, (high >> 4) + 1); 8 | if (2 <= high) { 9 | *next++ = 2; 10 | } 11 | 12 | for (i = 3; i <= high; i += 2) { 13 | if ((isprime[i >> 4] & (1 << ((i >> 1) & 7))) == 0) { 14 | *next++ = j = i; 15 | while ((j += i << 1) <= high) { 16 | isprime[j >> 4] |= 1 << ((j >> 1) & 7); 17 | } 18 | } 19 | } 20 | 21 | return next; 22 | } 23 | -------------------------------------------------------------------------------- /stringology/Hashing.cpp: -------------------------------------------------------------------------------- 1 | int q = 311; 2 | struct Hasher { // use two of those, with different mod (e.g. 1e9+7 and 1e9+9) 3 | string s; 4 | int mod; 5 | vector power, pref; 6 | Hasher(const string& s, int mod) : s(s), mod(mod) { 7 | power.pb(1); 8 | rep(i,1,s.size()) power.pb((ll)power.back() * q % mod); 9 | pref.pb(0); 10 | rep(i,0,s.size()) pref.pb(((ll)pref.back() * q % mod + s[i]) % mod); 11 | } 12 | int hash(int l, int r) { // compute hash(s[l..r]) with r inclusive 13 | return (pref[r+1] - (ll)power[r-l+1] * pref[l] % mod + mod) % mod; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /graphentheorie/kruskal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // edge_t fehlt, root und join ist das uebliche union-find 4 | int kruskal() { 5 | vector parent(nr_of_nodes, -1); 6 | int rem = nr_of_nodes - 1, ans = 0; 7 | 8 | sort(edges.begin(), edges.end()); 9 | for (vector::iterator it = edges.begin(); rem > 0 && it != edges.end(); ++it) { 10 | int a = root(parent, it->from), b = root(parent, it->to); 11 | if (a != b) { 12 | join(parent, a, b); 13 | ans += it->len; 14 | --rem; 15 | } 16 | } 17 | return ans; 18 | } 19 | -------------------------------------------------------------------------------- /rekurrenzen/subset-sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // liefert die groesste Summe von Elementen aus v, die kleiner oder gleich limit ist 5 | int subset_sum(const vector& v, int limit) { 6 | vector poss(limit + 1, false); 7 | int m = 0; 8 | 9 | poss[0] = true; 10 | for (vector::const_iterator it = v.begin(); it != v.end(); ++it) 11 | for (int j = m; j >= 0; --j) 12 | if (poss[j] && j + *it <= limit) { 13 | poss[j + *it] = true; 14 | m = max(m, j + *it); 15 | } 16 | 17 | return m; 18 | } 19 | -------------------------------------------------------------------------------- /arithmetik/romberg.cpp: -------------------------------------------------------------------------------- 1 | typedef double D; 2 | D f(D x) {return exp(-x * x);} //O(2^maxitr) function evaluations 3 | D Romberg(D a, D b, D(*f)(D), D eps, int maxitr = 25) { 4 | D T[maxitr][maxitr]; 5 | for (int i = 0; i < maxitr; ++i) { 6 | D h = (b - a) / (1 << i), x = a + h, pow = 4; 7 | T[i][0] = (f(a) + f(b)) / 2; 8 | for (int j = (1 << i) - 1; j >= 1; x += h, --j) T[i][0] += f(x); 9 | T[i][0] *= h; 10 | for (int j = 1; j <= i; pow *= 4, ++j) 11 | T[i][j] = T[i][j - 1] + (T[i][j - 1] - T[i - 1][j - 1]) / (pow - 1); 12 | if (i > 0 && abs(T[i][i] - T[i - 1][i - 1]) <= eps) return T[i][i]; 13 | } 14 | return T[maxitr - 1][maxitr - 1]; 15 | } 16 | -------------------------------------------------------------------------------- /geometrie/old/kreis.cpp: -------------------------------------------------------------------------------- 1 | // Schnittpunkte von Kreis um 0 mit Radius r1 mit Kreis um Punkt pos mit Radius r2 2 | vecvec isect(double r1, vec pos, double r2) { 3 | double d2 = (pos * pos).sum(), d = sqrt(d2); 4 | r1 *= r1; r2 *= r2; 5 | double x = 0.5 * (d2 + r1 - r2) / d, y2 = r1 - x * x; 6 | 7 | if (y2 > EPS) { 8 | double norma[] = { -pos[1], pos[0] }; 9 | vec norm(norma, 2); 10 | vecvec r(x / d * pos, 2); 11 | y2 = sqrt(y2); 12 | r[0] += y2 / d * norm; 13 | r[1] -= y2 / d * norm; 14 | return r; 15 | } else if (y2 > -EPS) { 16 | return vecvec(x / d * pos, 1); 17 | } 18 | return vecvec(); 19 | } 20 | -------------------------------------------------------------------------------- /graphentheorie/prim.cpp: -------------------------------------------------------------------------------- 1 | // alles wie bei Dijkstra 2 | int prim(vvii& gr) { 3 | vector dist(gr.size(), INF); 4 | priority_queue > kew; 5 | int ans = 0; 6 | 7 | dist[0] = 0; 8 | for (kew.push(ii(0, 0)); !kew.empty(); kew.pop()) { 9 | int d = kew.top().first, fr = kew.top().second; 10 | if (d <= dist[fr]) { 11 | ans += d; 12 | dist[fr] = -1; 13 | for (vii::iterator it = gr[fr].begin(); it != gr[fr].end(); ++it) { 14 | int to = it->first, len = it->second; 15 | if (dist[to] > len) kew.push(ii(dist[to] = len, to)); 16 | } 17 | } 18 | } 19 | return ans; 20 | } 21 | -------------------------------------------------------------------------------- /datenstrukturen/SkewHeap.cpp: -------------------------------------------------------------------------------- 1 | /* The simplest meldable priority queues: Skew Heap 2 | Merging (distroying both trees), inserting, deleting min: O(logn) amortised;*/ 3 | struct node{ 4 | int key; 5 | node *lc,*rc; 6 | node(int k):key(k),lc(0),rc(0){} 7 | }*root=0; 8 | int size=0; 9 | node* merge(node* x, node* y){ 10 | if(!x)return y; 11 | if(!y)return x; 12 | if(x->key > y->key)swap(x,y); 13 | x->rc=merge(x->rc,y); 14 | swap(x->lc,x->rc); 15 | return x; 16 | } 17 | void insert(int x) { root=merge(root,new node(x)); size++;} 18 | int delmin() { 19 | if(!root)return -1; 20 | int ret=root->key; 21 | node *troot=merge(root->lc,root->rc); 22 | delete root; 23 | root=troot; 24 | size--; 25 | return ret; 26 | } 27 | -------------------------------------------------------------------------------- /datenstrukturen/disjoint.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | class union_find 5 | { 6 | vector v; 7 | public: 8 | union_find(int n) {v = vector(n, -1);} 9 | 10 | int root(int i) {return v[i] < 0 ? i : (v[i] = root(v[i]));} 11 | 12 | void join(int i, int j) 13 | { 14 | if ((i = root(i)) == (j = root(j))) return; 15 | if (v[j] < v[i]) swap(i, j); 16 | v[i] += v[j]; 17 | v[j] = i; 18 | } 19 | 20 | int count_roots() { return count_if(v.begin(), v.end(), bind2(less(), 0));} 21 | 22 | vector get_roots() 23 | { 24 | vector r; 25 | remove_copy_if(v.begin(), v.end(), back_inserter(r), bind2nd(greater_equal(), 0)); 26 | return r; 27 | } 28 | }; -------------------------------------------------------------------------------- /stringology/Z_Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* calculate the $z array for string $s of length $n in O(n) time. 2 | * z[i] := the longest common prefix of s[0..n-1] and s[i..n-1]. 3 | * For pattern matching, make a string P$S and output positions with z[i]==|P| 4 | * For pattern matching, there's no need to store (but to calculate) z[i] for i>|P|. */ 5 | void calc_Z(const char *s, int n, int *z) { 6 | int l = 0, r = 0, p, q; 7 | if(n > 0) z[0] = n; 8 | for (int i = 1; i < n; ++i) { 9 | if (i <= r && z[i - l] < r - i + 1) { 10 | z[i] = z[i - l]; 11 | } else { 12 | if (i > r) p = 0, q = i; 13 | else p = r - i + 1, q = r + 1; 14 | while (q < n && s[p] == s[q]) ++p, ++q; 15 | z[i] = q - i, l = i, r = q - 1; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /graphentheorie/topo-sort.cpp: -------------------------------------------------------------------------------- 1 | // Gibt Knotenindizes in topologischer Reihenfolge, retval.size() < graph.size() falls Zyklen vorkommen 2 | vector topsort(const vector >& graph) 3 | { 4 | vector preds(graph.size(), 0); 5 | for (size_t i = 0; i < graph.size(); i++) 6 | for (size_t j = 0; j < graph[i].size(); j++) 7 | preds[graph[i][j]]++; 8 | 9 | std::queue q; 10 | for (size_t i = 0; i < preds.size(); i++) 11 | if (!preds[i]) q.push(i); 12 | 13 | vector sorted; 14 | while (!q.empty()) { 15 | int curr = q.front(); q.pop(); 16 | sorted.push_back(curr); 17 | for (size_t i = 0; i < graph[curr].size(); i++) 18 | if (!(--preds[graph[curr][i]])) 19 | q.push(graph[curr][i]); 20 | } 21 | return sorted; 22 | } -------------------------------------------------------------------------------- /graphentheorie/BipartiteMatching2.cpp: -------------------------------------------------------------------------------- 1 | // run time: O(n * min(ans^2, |E|)), where n is the size of the left side 2 | vector adj[1001]; // adjacency list 3 | int iter, match[1001], vis[1001]; 4 | bool dfs(int x) { 5 | if (vis[x] == iter) return 0; 6 | vis[x] = iter; 7 | for (auto y : adj[x]) { 8 | if (match[y] < 0 || dfs(match[y])) { 9 | match[y] = x, match[x] = y; 10 | return 1; 11 | } 12 | } 13 | return 0; 14 | } 15 | int kuhn(int n) { // n = nodes on left side (numbered 0..n-1) 16 | memset(match,-1,sizeof match) ;// to accelerate, initialize with a greedy matching 17 | int ans = 0; 18 | for (int i = 0; i < n; ++i) { 19 | ++iter; 20 | ans += dfs(i); 21 | } 22 | return ans; 23 | } 24 | -------------------------------------------------------------------------------- /stringology.tex: -------------------------------------------------------------------------------- 1 | \section{Stringology} 2 | 3 | \subsection{Z Algorithm} 4 | \lstinputlisting{stringology/Z_Algorithm.cpp} 5 | 6 | \subsection{KMP} 7 | \lstinputlisting{niklas/kmp.cpp} 8 | 9 | %\subsection{Manacher Algorithm (finding the longest palindrome)} 10 | 11 | %\lstinputlisting{stringology/Manacher.cpp} 12 | 13 | \subsection{Rolling hash} 14 | \lstinputlisting{stringology/Hashing.cpp} 15 | 16 | %\subsection{Suffix Array} 17 | 18 | %\lstinputlisting{stringology/suffixarray.cpp} 19 | 20 | \subsection{Suffix Array - LCP Based} 21 | 22 | \lstinputlisting{niklas/suffixarray_lcp_based.cpp} 23 | 24 | \subsection{Suffix automaton} 25 | \lstinputlisting{niklas/suffix_automaton.cpp} 26 | 27 | \subsection{Aho-Corasick automaton} 28 | \lstinputlisting{niklas/aho_corasick.cpp} 29 | -------------------------------------------------------------------------------- /parser/arith-eval.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // erst ptr setzen, dann Aufruf von parse() 4 | char* ptr; 5 | 6 | double atom(); 7 | double prod(); 8 | double parse(); 9 | 10 | double atom() { // Anpassen wenn unaerer - zulaessig 11 | double res; 12 | if (*ptr == '(') { 13 | ++ptr; 14 | res = parse(); 15 | ++ptr; 16 | } else res = strtod(ptr, &ptr); 17 | return res; 18 | } 19 | 20 | double prod() { 21 | double res = atom(); 22 | while (*ptr == '*' || *ptr == '/') 23 | res = *ptr++ == '*' ? res * atom() : res / atom(); 24 | return res; 25 | } 26 | 27 | double parse() { 28 | double res = prod(); 29 | while (*ptr == '+' || *ptr == '-') 30 | res = *ptr++ == '+' ? res + prod() : res - prod(); 31 | return res; 32 | } 33 | -------------------------------------------------------------------------------- /arithmetik/lr.cpp: -------------------------------------------------------------------------------- 1 | const int MAX = 42; 2 | void lr(double a[MAX][MAX], int n) { 3 | for (int i = 0; i < n; ++i) { 4 | for (int k = 0; k < i; ++k) a[i][i] -= a[i][k] * a[k][i]; 5 | for (int j = i + 1; j < n; ++j) { 6 | for (int k = 0; k < i; ++k) a[j][i] -= a[j][k] * a[k][i]; 7 | a[j][i] /= a[i][i]; 8 | for (int k = 0; k < i; ++k) a[i][j] -= a[i][k] * a[k][j]; 9 | } 10 | } 11 | } 12 | double det(double a[MAX][MAX], int n) { 13 | lr(a, n); 14 | double d = 1; 15 | for (int i = 0; i < n; ++i) d *= a[i][i]; 16 | return d; 17 | } 18 | void solve(double a[MAX][MAX], double *b, int n) { 19 | for (int i = 1; i < n; ++i) 20 | for (int j = 0; j < i; ++j) b[i] -= a[i][j] * b[j]; 21 | for (int i = n - 1; i >= 0; --i) { 22 | for (int j = i + 1; j < n; ++j) b[i] -= a[i][j] * b[j]; 23 | b[i] /= a[i][i]; 24 | } 25 | } -------------------------------------------------------------------------------- /arithmetik/bigint.java: -------------------------------------------------------------------------------- 1 | import java.lang.*; 2 | import java.util.*; 3 | import java.io.*; 4 | import java.math.*; 5 | 6 | class Main { 7 | final static int MAX = 255; 8 | static BigInteger[] fac; 9 | static void initFac() { 10 | BigInteger bi = BigInteger.ONE; 11 | fac = new BigInteger[MAX + 1]; 12 | fac[0] = BigInteger.ONE; 13 | for (int i = 1; i <= MAX; ++i) { 14 | fac[i] = fac[i - 1].multiply(bi); 15 | bi = bi.add(BigInteger.ONE); 16 | } 17 | } 18 | public static void main(String[] args) { 19 | Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in))); 20 | while (sc.hasNextInt()) { 21 | int total = sc.nextInt(); 22 | BigInteger rank = sc.nextBigInteger(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | using ll=long long; 6 | using ld=long double; 7 | using pii=pair; 8 | using vi=vector; 9 | #define rep(i,s,e) for (int i=(s);i<(e);++i) 10 | #define all(x) begin(x),end(x) 11 | #define clr(x,y) memset(x,y,sizeof x) 12 | #define contains(x,y) ((x).find(y)!=end(x)) 13 | #define mk make_pair 14 | #define fst first 15 | #define snd second 16 | #define pb push_back 17 | #define endl "\n" 18 | const int dx[]={0,0,1,-1,1,-1,1,-1}, dy[]={-1,1,0,0,1,-1,-1,1}; 19 | void run(); 20 | int main() { 21 | ios::sync_with_stdio(0); 22 | cout << fixed << setprecision(16); 23 | rlim_t stacksz = 64*1024*1024; 24 | rlimit rl{stacksz,stacksz}; 25 | setrlimit(RLIMIT_STACK, &rl); // should return 0 26 | run(); 27 | } 28 | void run() { } 29 | -------------------------------------------------------------------------------- /graphentheorie/Maxflow_EK.cpp: -------------------------------------------------------------------------------- 1 | umap> a; 2 | void init() { a.clear(); } 3 | void addedge(int i, int j, int c) { a[i][j] += c; } 4 | int ek(int S, int T) { 5 | int flow = 0; 6 | for(;;) { 7 | umap p, m; 8 | queue q; 9 | q.push(S); 10 | p[S] = S; 11 | m[S] = inf; 12 | while (!q.empty()) { 13 | int x = q.front(); 14 | q.pop(); 15 | for (auto& e: a[x]) { 16 | int y = e.first, c = e.second; 17 | if (!c || contains(p, y)) continue; 18 | p[y] = x; 19 | m[y] = min(m[x], c); 20 | q.push(y); 21 | } 22 | } 23 | if (!contains(p, T)) break; 24 | int delta = m[T]; 25 | for (int x = T; p[x] != x; x = p[x]) { 26 | a[p[x]][x] -= delta; 27 | a[x][p[x]] += delta; 28 | } 29 | flow += delta; 30 | } 31 | return flow; 32 | } 33 | -------------------------------------------------------------------------------- /stringology/Manacher.cpp: -------------------------------------------------------------------------------- 1 | /* Interleave s with '#' and prepend a '$': abcd => $#a#b#c#d#; len(news) = 2*n+2; 2 | * returns an array $P of length 2*n+2 in O(n) time where: 3 | * P[i] is the maxlen which can be extended from i (inclusive) to the left and right. 4 | * P[i]-1 is the max. length of palindrome centered at i. 5 | * start position of this palindrome in orig. string is i/2 - (P[i] + (i%2 == 0))/2 */ 6 | void Manacher(char *s, int n, int *P) { 7 | static char ts[mlen * 2 + 2]; 8 | int N = 2 * n + 2; 9 | ts[0] = '$', ts[N - 1] = '#'; 10 | for (int i = 0; i < n; ++i) ts[i * 2 + 1] = '#', ts[i * 2 + 2] = s[i]; 11 | int mx = 0, id = 0; 12 | memset(P, 0, sizeof(int) * N); 13 | for (int i = 1; i < N; i++) { 14 | P[i] = mx > i ? min(P[2 * id - i], mx - i) : 1; 15 | while (ts[i + P[i]] == ts[i - P[i]]) ++P[i]; 16 | if (i + P[i] > mx) mx = i + P[i], id = i; 17 | } 18 | } -------------------------------------------------------------------------------- /graphentheorie/dijkstra2.cpp: -------------------------------------------------------------------------------- 1 | const int mn = 50005, inf = 0x3f3f3f3f; 2 | typedef vector VINT; 3 | struct heapcomp{ 4 | int *ref; 5 | heapcomp(int *r) : ref(r) { } 6 | bool operator()(int a, int b) { return ref[a] > ref[b]; } 7 | }; 8 | int dijkstra(int n, const VINT g[], const VINT c[], int s, int t, int *dis, int *pre) { 9 | static int h[mn], sz; 10 | for (int i = 0; i < n; ++i) dis[i] = inf, pre[i] = -1; 11 | dis[s] = 0, sz = 1, h[0] = s; 12 | heapcomp cmp(dis); 13 | while (sz > 0) { 14 | int top = h[0]; 15 | pop_heap(h, h + sz--, cmp); 16 | if (top == t) return dis[top]; 17 | for (size_t i = 0; i < g[top].size(); ++i) { 18 | if (dis[g[top][i]] > dis[top] + c[top][i]) { 19 | dis[g[top][i]] = dis[top] + c[top][i]; 20 | pre[g[top][i]] = top; 21 | h[sz++] = g[top][i]; 22 | push_heap(h, h + sz, cmp); 23 | } 24 | } 25 | } 26 | return -1; 27 | } 28 | -------------------------------------------------------------------------------- /arithmetik/gauss.cpp: -------------------------------------------------------------------------------- 1 | #define EPSILON 0.0000001 2 | 3 | bool LGS(double** A, double* b, int m, int n, double* res){ 4 | int bla[n];//Werte von 0..m-1 5 | memset(bla,-1,n*sizeof(int)); 6 | int x,y,x2,y2; 7 | for(y=0;yEPSILON)return false; 11 | else continue; 12 | } 13 | for(x2=x+1;x2 2 | 3 | #define FROM_N 1000 4 | #define TO_N 1000 5 | 6 | int from_nodes, to_nodes; 7 | 8 | bool graph[FROM_N][TO_N], seen[TO_N]; 9 | 10 | int match_from[FROM_N], match_to[TO_N]; 11 | 12 | bool match_visit(int from) { 13 | for (int to = 0; to < to_nodes; ++to) { 14 | if (graph[from][to] && !seen[to]) { 15 | seen[to] = true; 16 | 17 | if (match_to[to] < 0 || match_visit(match_to[to])) { 18 | match_from[from] = to; 19 | match_to[to] = from; 20 | return true; 21 | } 22 | } 23 | } 24 | 25 | return false; 26 | } 27 | 28 | int match() { 29 | int res = 0; 30 | 31 | fill(match_from, match_from + from_nodes, -1); 32 | fill(match_to, match_to + to_nodes, -1); 33 | for (int i = 0; i < from_nodes; ++i) { 34 | fill(seen, seen + to_nodes, false); 35 | if (match_visit(i)) { 36 | ++res; 37 | } 38 | } 39 | 40 | return res; 41 | } 42 | -------------------------------------------------------------------------------- /graphentheorie/Maxflow_CS.cpp: -------------------------------------------------------------------------------- 1 | // FF with cap scaling, O(m^2 log C) 2 | const int MAXN = 190000, MAXC = 1<<29; 3 | struct edge { int dest, capacity, rev; }; 4 | vector adj[MAXN]; 5 | int vis[MAXN], target, iter, cap; 6 | 7 | void addedge(int x, int y, int c) { 8 | adj[x].push_back(edge {y, c, (int)adj[y].size()}); 9 | adj[y].push_back(edge {x, 0, (int)adj[x].size() - 1}); 10 | } 11 | 12 | bool dfs(int x) { 13 | if (x == target) return 1; 14 | if (vis[x] == iter) return 0; 15 | vis[x] = iter; 16 | for (edge& e: adj[x]) 17 | if (e.capacity >= cap && dfs(e.dest)) { 18 | e.capacity -= cap; 19 | adj[e.dest][e.rev].capacity += cap; 20 | return 1; 21 | } 22 | return 0; 23 | } 24 | 25 | int maxflow(int S, int T) { 26 | cap = MAXC, target = T; 27 | int flow = 0; 28 | while(cap) { 29 | while(++iter, dfs(S)) 30 | flow += cap; 31 | cap /= 2; 32 | } 33 | return flow; 34 | } 35 | -------------------------------------------------------------------------------- /graphentheorie/scc_old.cpp: -------------------------------------------------------------------------------- 1 | vvi gr; 2 | vi nr, low; 3 | stack S; 4 | vvi sccs; 5 | vector inst; 6 | int idx = 0; 7 | 8 | void visit (int i) { 9 | nr[i] = low[i] = idx++; 10 | S.push (i); 11 | in_stack[i] = true; 12 | for (vi::iterator it = gr[i].begin (); it != gr[i].end (); ++it) { 13 | if (nr[*it] < 0) { 14 | visit (*it); 15 | low[i] = min (low[i], low[*it]); 16 | } else if (in_stack[*it]) { 17 | low[i] = min (low[i], low[*it]); 18 | } 19 | } 20 | if (nr[i] == low[i]) { 21 | int n; 22 | vi comp; 23 | do { 24 | n = S.top (); S.pop (); 25 | in_stack[n] = false; 26 | comp.push_back (n); 27 | } while (n != i); 28 | sccs.push_back (comp); 29 | } 30 | } 31 | 32 | void scc () { 33 | nr.resize (gr.size (), -1); 34 | low.resize (gr.size ()); 35 | inst.resize (gr.size (), false); 36 | for (int i = 0; i < gr.size (); ++i) { 37 | if (nr[i] < 0) { 38 | visit (i); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /geometrie/old/bresenham.cpp: -------------------------------------------------------------------------------- 1 | // ruft do_something(x, y) mit allen (x, y) auf, 2 | // die eine gerasterte Linie von (x0, y0) nach (x1, y1) bilden 3 | void line(int x0, int y0, int x1, int y1) { 4 | int dx = x1 - x0, dy = y1 - y0; 5 | int incrE = 2 * dy, incrNE = 2 * (dy - dx); 6 | int d = 2 * dy - dx, x = x0, y = y0; 7 | do_something(x, y); 8 | while (x < x1) { 9 | if (d > 0) { d += incrNE; ++y; } else d += incrE; 10 | do_something(++x, y); 11 | } 12 | } 13 | // ruft do_something(x, y) mit allen (x, y) auf, 14 | // die einen gerasterten Achtelkreis um den Ursprung bilden 15 | void circle(int radius) { 16 | int deltaE = 3, deltaSE = -2 * radius + 5; 17 | int d = 1 - radius, x = 0, y = radius; 18 | do_something(x, y); 19 | while (x < y) { 20 | if (d < 0) d += deltaE; else { d += deltaSE; deltaSE += 2; --y; } 21 | deltaE += 2; deltaSE += 2; 22 | do_something(++x, y); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /graphentheorie/bellman-ford.cpp: -------------------------------------------------------------------------------- 1 | #define INFTY 0x7FFFFFFF 2 | 3 | struct edge {int to; int len;}; 4 | 5 | // Rueckgabe ist Array mit den Entfernungen oder leerer vector wenn der Graph einen negativen Kreis hat 6 | vector bellman_ford(const vector >& graph, int source) { 7 | vector dist(graph.size(), INFTY); 8 | dist[source] = 0; 9 | for (size_t j = 1; j < graph.size(); j++) { 10 | for (size_t from = 0; from < graph.size(); from++) 11 | for (size_t i = 0; i < graph[from].size()]; i++) { 12 | const int& to = graph[from][i].to; 13 | int cdist = dist[from] + graph[from][i].len; 14 | if (cdist < dist[to]) dist[to] = cdist; 15 | } 16 | } 17 | for (size_t from = 0; from < graph.size(); from++) 18 | for (size_t i = 0; i < graph[from].size(); i++) { 19 | const int& to = graph[from][i].to; 20 | int cdist = dist[from] + graph[from][i].len; 21 | if (cdist < dist[to]) return vector(); 22 | } 23 | return dist; 24 | } -------------------------------------------------------------------------------- /parser/cyk.cpp: -------------------------------------------------------------------------------- 1 | #define MAX 1024 2 | 3 | #define TERMINALS 7 4 | #define NONTERMINALS 14 5 | 6 | // #define A 1, #define MOD 2, #define BA 4, usw fuer alle Nichtterminale 7 | // SENTENCE ist die Axiom 8 | 9 | int nonterminal_map[NONTERMINALS][NONTERMINALS], words, symbol[MAX][MAX]; 10 | 11 | // am Anfang in symbol[i][i] die Maske des Nichtterminals des i-ten Wortes eintragen 12 | bool cyk() { 13 | int i, j, k, m, n; 14 | for (i = 1; i < words; ++i) 15 | for (j = 0; j + i < words; ++j) { 16 | symbol[j][j + i] = 0; 17 | for (k = 0; k < i; ++k) 18 | for (m = 0; m < NONTERMINALS; ++m) 19 | for (n = 0; n < NONTERMINALS; ++n) 20 | if ((symbol[j][j + k] & (1 << m)) 21 | && (symbol[j + k + 1][j + i] & (1 << n))) 22 | symbol[j][j + i] |= nonterminal_map[m][n]; 23 | } 24 | return words > 0 && (symbol[0][words - 1] & SENTENCE); 25 | } 26 | -------------------------------------------------------------------------------- /geometrie/old/poly-punkt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX 1024 4 | #define EPS 1e-7 5 | 6 | struct point { 7 | double x, y; 8 | }; 9 | 10 | struct polygon { 11 | int n; 12 | point p[MAX]; 13 | point &operator[](int i) { 14 | return p[i]; 15 | } 16 | }; 17 | 18 | inline double dist(const point &a, const point &b) { 19 | double dx = a.x - b.x, dy = a.y - b.y; 20 | return sqrt(dx * dx + dy * dy); 21 | } 22 | 23 | bool contains(polygon &P, point &p) { 24 | bool inside = false; 25 | 26 | for (int j = P.n - 1, i = 0; i < P.n; j = i++) { 27 | if (fabs(dist(p, P[j]) + dist(p, P[i]) - dist(P[j], P[i])) < EPS) { 28 | return true; // true = Rand gehoert mit zum Polygon 29 | } 30 | 31 | if (min(P[j].y, P[i].y) <= p.y && max(P[j].y, P[i].y) > p.y && 32 | (p.y - P[j].y) * (P[i].x - P[j].x) / (P[i].y - P[j].y) > p.x - P[j].x) { 33 | inside = !inside; 34 | } 35 | } 36 | return inside; 37 | } 38 | -------------------------------------------------------------------------------- /parser.tex: -------------------------------------------------------------------------------- 1 | \section{Parser} 2 | 3 | \subsection{Rekursiver Parser f"ur arithmetische Ausdr"ucke} 4 | 5 | \lstinputlisting{parser/arith-eval.cpp} 6 | 7 | \subsection{Umwandlung von Infix- nach Postfix-Notation} 8 | 9 | \lstinputlisting{parser/infix-postfix.cpp} 10 | 11 | \subsection{Bottom-up-Parser nach Cocke, Younger und Kasami} 12 | 13 | Eine kontextfreie Grammatik ist in Chomsky-Normalform, wenn jede Produktion eine der folgenden Formen hat: 14 | \[ S \to \varepsilon, \quad A \to a, \quad A \to BC \] 15 | Um Grammatik in CNF zu bringen, folgende Schritte: 16 | \begin{itemize} 17 | \item Jedem Terminal ein Nichtterminal zuordnen, Produktion \(X_a \to a\) einf"ugen. 18 | \item Wenn wo mehr als zwei Nichtterminale stehen, immer zwei zu einem neuen Symbol zusammenfassen und 19 | entsprechende Produktion einf"ugen. 20 | \item \(\varepsilon\)-Produktionen entfernen. 21 | \item Kettenproduktionen (\(A \to B\) entfernen, indem \(B\) nacheinander durch alle seine Folgeprodukte ersetzt wird. 22 | \end{itemize} 23 | \lstinputlisting{parser/cyk.cpp} 24 | -------------------------------------------------------------------------------- /graphentheorie/floyd-warshall.cpp: -------------------------------------------------------------------------------- 1 | const int MAX = 100, INF = 12345678; 2 | 3 | // N = Anzahl Knoten 4 | // gr[i][j] = Kosten von Knoten i nach Knoten j 5 | // nach Aufruf: via[i][j] = naechster Knoten auf dem kuerzesten Pfad von i nach j 6 | int N, via[MAX][MAX], gr[MAX][MAX]; 7 | 8 | // wer nur die Distanzen braucht, nicht die tatsaechlichen Wege, 9 | // kann auch alles mit "via" weglassen 10 | void floydwarsh() { 11 | for (int i = 0; i < N; ++i) 12 | for (int j = 0; j < N; ++j) 13 | via[i][j] = j; 14 | for (int k = 0; k < N; ++k) 15 | for (int i = 0; i < N; ++i) 16 | for (int j = 0; j < N; ++j) 17 | if (gr[i][j] > gr[i][k] + gr[k][j]) { 18 | gr[i][j] = gr[i][k] + gr[k][j]; 19 | via[i][j] = k; 20 | } 21 | for (int i = 0; i < N; ++i) 22 | for (int j = 0; j < N; ++j) 23 | if (gr[i][j] < INF) 24 | while (via[i][j] != via[i][via[i][j]]) 25 | via[i][j] = via[i][via[i][j]]; 26 | } 27 | -------------------------------------------------------------------------------- /zahlentheorie/miller-rabin.cpp: -------------------------------------------------------------------------------- 1 | typedef unsigned long long ull; 2 | const struct zero_t { 3 | int z[0x10000]; 4 | zero_t() { 5 | for (int i = 1; i < 0x10000; ++i) z[i] = (i & 1) ? 0 : 1 + z[i >> 1]; 6 | } 7 | } trail; 8 | inline bool isprob(unsigned nr, unsigned base) { 9 | unsigned u = 1, odd = nr - 1, sh = (odd & 0xFFFF) 10 | ? trail.z[odd & 0xFFFF] : 16 + trail.z[odd >> 16]; 11 | for (odd >>= sh; odd > 0; odd >>= 1) { 12 | if ((odd & 1)) u = (ull(u) * base) % nr; 13 | base = (ull(base) * base) % nr; 14 | } 15 | if (u == 1) return true; 16 | while (sh-- > 0) { 17 | if (u == nr - 1) return true; 18 | u = (ull(u) * u) % nr; 19 | } 20 | return false; 21 | } 22 | bool isprime(unsigned nr) { 23 | static const unsigned p[] = { 2, 3, 5, 7, 11, 13, 17, 19 }; 24 | for (int i = 0; i < 8; ++i) { 25 | if (p[i] * p[i] > nr) return nr > 1; 26 | if (nr % p[i] == 0) return false; 27 | } 28 | return isprob(nr, 2) && isprob(nr, 7) && isprob(nr, 61); 29 | } 30 | -------------------------------------------------------------------------------- /graphentheorie/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | const int INF = 12345678; 7 | 8 | typedef pair ii; 9 | typedef vector vii; 10 | typedef vector vvii; 11 | 12 | // Anzahl der Knoten = gr.size() 13 | // Grad des Knotens i = gr[i].size() 14 | // j-ter benachbarter Knoten des Knotens i = gr[i][j].first 15 | // Laenge dieser Kante = gr[i][j].second 16 | vector dijkstra(vvii& gr, int src) { 17 | vector dist(gr.size(), INF); 18 | priority_queue > kew; 19 | 20 | dist[src] = 0; 21 | for (kew.push(ii(0, src)); !kew.empty(); kew.pop()) { 22 | int d = kew.top().first, fr = kew.top().second; 23 | if (d <= dist[fr]) { 24 | for (vii::iterator it = gr[fr].begin(); it != gr[fr].end(); ++it) { 25 | int to = it->first, len = it->second; 26 | if (dist[to] > d + len) kew.push(ii(dist[to] = d + len, to)); 27 | } 28 | } 29 | } 30 | 31 | return dist; 32 | } 33 | -------------------------------------------------------------------------------- /zahlentheorie/euclid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | typedef valarray ai; 8 | typedef vector vi; 9 | 10 | // a % euclid(a, b)[0] == 0 11 | // b % euclid(a, b)[0] == 0 12 | // euclid(a, b)[0] == a * euclid(a, b)[1] + b * euclid(a, b)[2] 13 | ai euclid(int a, int b) { 14 | int R[] = { a, 1, 0 }, S[] = { b, 0, 1 }; 15 | ai r(R, 3), s(S, 3); 16 | 17 | while (s[0] != 0) { 18 | r -= r[0] / s[0] * s; 19 | swap(r, s); 20 | } 21 | 22 | return r; 23 | } 24 | 25 | // alle Loesungen von (a * x) % m == b mit 0 <= x < m 26 | vi cong_solv(int a, int b, int m) { 27 | ai gcd = euclid(a, m); 28 | vi res; 29 | 30 | if (b % gcd[0] == 0) { 31 | m /= gcd[0]; 32 | int inv = gcd[1] < 0 ? (m - (-gcd[1] % m)) % m : gcd[1] % m, 33 | sol = (b / gcd[0] * inv) % m; 34 | for (int i = gcd[0]; i > 0; --i) { 35 | res.push_back(sol); 36 | sol += m; 37 | } 38 | } 39 | 40 | return res; 41 | } 42 | -------------------------------------------------------------------------------- /datenstrukturen/trie-array.cpp: -------------------------------------------------------------------------------- 1 | #define ALPHA 'A' 2 | struct trie { 3 | struct trie *down[26]; 4 | bool end_of_word; 5 | } node[100000]; // ggf. Anzahl anpassen 6 | int nodes = 0; // so macht man alle Tries ungueltig 7 | struct trie *root = NULL; // so loescht man einen einzelnen Trie 8 | // Aufruf mit add(&root, str); gibt true zurueck, wenn Wort noch nicht vorhanden war 9 | bool add(struct trie **root_ptr, char *word) { 10 | struct trie *p; 11 | do { 12 | p = *root_ptr; 13 | if (p == NULL) { 14 | p = node + nodes++; 15 | for (int i = 0; i < 26; ++i) p->down[i] = NULL; 16 | p->end_of_word = false; 17 | *root_ptr = p; 18 | } 19 | root_ptr = p->down + (*word - ALPHA); 20 | } while (*word++); 21 | return p->end_of_word ? false : (p->end_of_word = true); 22 | } 23 | // Aufruf mit check(root, str); gibt true zurueck, wenn Wort vorhanden 24 | bool check(struct trie *root, char *word) { 25 | while (*word) { 26 | if (root == NULL) return false; 27 | root = root->down[*word++ - ALPHA]; 28 | } 29 | return root != NULL && root->end_of_word; 30 | } 31 | -------------------------------------------------------------------------------- /arithmetik/fft.cpp: -------------------------------------------------------------------------------- 1 | typedef double D; // or long double? 2 | typedef complex cplx; // use own implementation for 2x speedup 3 | const D pi = acos(-1); // or -1.L for long double 4 | 5 | // input should have size 2^k 6 | vector fft(const vector& a, bool inv=0) { 7 | int logn=1, n=a.size(); 8 | vector A(n); 9 | while((1<>k)&1); 13 | A[j] = a[i]; } 14 | for(int s=2; s<=n; s<<=1) { 15 | D ang = 2 * pi / s * (inv ? -1 : 1); 16 | cplx ws(cos(ang), sin(ang)); 17 | for(int j=0; j a = {0,0,0,0,1,2,3,4}, b = {0,0,0,0,2,3,0,1}; // polynomials 28 | a = fft(a); b = fft(b); 29 | rep(i,0,a.size()) a[i] *= b[i]; // convult spectrum 30 | a = fft(a,1); // ifft, a = a * b 31 | -------------------------------------------------------------------------------- /zahlentheorie/BinomialModK.cpp: -------------------------------------------------------------------------------- 1 | // calculate (product_{i=1,i%p!=0}^n i) % p^e. cnt is the exponent of p in n! 2 | // Time: p^e + log(p, n) 3 | int get_part_of_fac_n_mod_pe(int n, int p, int mod, int *upto, int &cnt) { 4 | if (n < p) { cnt = 0; return upto[n];} 5 | else { 6 | int res = powmod(upto[mod], n / mod, mod); 7 | res = (ll) res * upto[n % mod] % mod; 8 | res = (ll) res * get_part_of_fac_n_mod_pe(n / p, p, mod, upto, cnt) % mod; 9 | cnt += n / p; 10 | return res; 11 | } 12 | } 13 | //C(n,k) % p^e. Use Chinese Remainder Theorem to get C(n,k)%m 14 | int get_n_choose_k_mod_pe(int n, int k, int p, int mod) { 15 | static int upto[maxm + 1]; 16 | upto[0] = 1 % mod; 17 | for (int i = 1; i <= mod; ++i) 18 | upto[i] = i % p ? (ll) upto[i - 1] * i % mod : upto[i - 1]; 19 | int cnt1, cnt2, cnt3; 20 | int a = get_part_of_fac_n_mod_pe(n, p, mod, upto, cnt1); 21 | int b = get_part_of_fac_n_mod_pe(k, p, mod, upto, cnt2); 22 | int c = get_part_of_fac_n_mod_pe(n - k, p, mod, upto, cnt3); 23 | int res = (ll) a * modinv(b, mod) % mod * modinv(c, mod) % mod * powmod(p, cnt1 - cnt2 - cnt3, mod) % mod; 24 | return res; 25 | } 26 | // Lucas's Theorem (p prime, m_i,n_i base p repr. of m, n): binom(m,n)==procduct(binom(m_i,n_i)) (mod p) 27 | -------------------------------------------------------------------------------- /graphentheorie/stoer-wagner.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int N = 200, MAXWEIGHT = 1001, MAXCUT = N*N*MAXWEIGHT; 4 | int g[N][N]; // ungerichteter graph als adjazensmatrix 5 | int v[N]; // besucht-status 6 | int c[N]; // kosten, um aus bisher besuchter menge zu knoten zu kommen 7 | int n; // knotenanzahl 8 | 9 | int mincut() { 10 | memset(v, 0, sizeof(v)); 11 | int bestcut = MAXCUT; 12 | for(int iter = 1; iter < n; ++iter) { 13 | memset(c, 0, sizeof(c)); 14 | int t = 0, s = 0, w = MAXCUT; 15 | for(int nvis = iter; nvis < n; ++nvis) { 16 | v[t] = iter; 17 | int cmax = 0, next = -1; 18 | for( int i = 0; i < n; ++i ) // c[i] updaten und groesstes merken 19 | if(v[i] < iter ) { 20 | if(g[t][i]) c[i] += g[t][i]; 21 | if( c[i] && c[i] > cmax ) cmax = c[i], next = i; 22 | } 23 | 24 | if( next == -1 ) { // graph unzusammenhaengend 25 | w = 0; break; 26 | } 27 | s = t; t = next; w = cmax; 28 | } 29 | if( w < bestcut ) { 30 | bestcut = w; // trennt s und t 31 | } 32 | for( int i = 0; i < n; ++i ) // knotenkontraktion s,t -> t 33 | if( i != t && g[s][i]) { 34 | g[t][i] += g[s][i], g[i][t] += g[s][i]; 35 | } 36 | v[s] = N; // knoten "s" nie mehr besuchen 37 | } 38 | return bestcut; 39 | } 40 | -------------------------------------------------------------------------------- /graphentheorie/arti-bruecken.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | const int MAX = 1024; 6 | 7 | vector > graph; 8 | int low[MAX], depth[MAX]; 9 | bool is_arti[MAX], is_bridge[MAX][MAX]; 10 | 11 | int visit(int nod, int par, int dep) { 12 | int children = 0; 13 | 14 | low[nod] = depth[nod] = dep; 15 | for (size_t i = 0; i < graph[nod].size(); ++i) { 16 | int k = graph[nod][i]; 17 | 18 | if (depth[k] < 0) { 19 | ++children; 20 | visit(k, nod, dep + 1); 21 | if (low[nod] > low[k]) low[nod] = low[k]; 22 | is_arti[nod] = is_arti[nod] || low[k] >= dep; 23 | is_bridge[nod][i] = low[k] > dep; 24 | } else if (k != par) { 25 | if (low[nod] > depth[k]) low[nod] = depth[k]; 26 | is_bridge[nod][i] = false; 27 | } 28 | } 29 | return children; 30 | } 31 | 32 | void tarjan() { 33 | fill(depth, depth + graph.size(), -1); 34 | fill(is_arti, is_arti + graph.size(), false); 35 | for (size_t i = 0; i < graph.size(); ++i) 36 | fill(is_bridge[i], is_bridge[i] + graph[i].size(), true); 37 | for (size_t i = 0; i < graph.size(); ++i) 38 | if (depth[i] < 0) is_arti[i] = visit(i, i, 0) > 1; 39 | } 40 | -------------------------------------------------------------------------------- /datenstrukturen/trie-list.cpp: -------------------------------------------------------------------------------- 1 | struct trie { 2 | struct trie *next, *down; 3 | char letter; 4 | } node[1000000]; /* ggf. Anzahl anpassen */ 5 | int nodes = 0; /* so macht man alle Tries ungueltig */ 6 | struct trie *root = NULL; /* so loescht man einen einzelnen Trie */ 7 | /* Aufruf mit add(&root, str); gibt true zurueck, wenn Wort noch nicht vorhanden war */ 8 | int add(struct trie **root_pp, char *word) { 9 | struct trie *p, **prev_pp; 10 | int n = nodes; 11 | do { 12 | for (prev_pp = root_pp; (p = *prev_pp) != NULL && p->letter < *word; 13 | prev_pp = &(p->next)) {} 14 | if (p == NULL || p->letter != *word) { 15 | p = node + nodes++; 16 | p->next = *prev_pp; 17 | p->down = NULL; 18 | p->letter = *word; 19 | *prev_pp = p; 20 | } 21 | root_pp = &p->down; 22 | } while (*word++); 23 | return n < nodes; 24 | } 25 | /* Aufruf mit check(root, str); gibt true zurueck, wenn Wort vorhanden */ 26 | int check(struct trie *root, char *word) { 27 | do { 28 | while (root != NULL && root->letter < *word) root = root->next; 29 | if (root == NULL || root->letter != *word) return 0; 30 | root = root->down; 31 | } while (*word++); 32 | return 1; 33 | } 34 | -------------------------------------------------------------------------------- /graphentheorie/BipartiteMatching.cpp: -------------------------------------------------------------------------------- 1 | const int mn1 = 501, mn2 = 501; 2 | struct node { 3 | int v; 4 | node *next; 5 | }*g[mn1], pool[mn1 * mn2]; 6 | int pp; 7 | bool succeed(int v, int *mx, int *my, bool *vis) { 8 | for (node *i = g[v]; i; i = i->next) 9 | if (!vis[i->v]) { 10 | vis[i->v] = 1; 11 | if (my[i->v] == -1 || succeed(my[i->v], mx, my, vis)) 12 | return mx[v] = i->v, my[i->v] = v, 1; 13 | } 14 | return 0; 15 | }/* n1, n2: the number of vertices on the left/right 16 | int mx[i = 0..mn1-1]: the vertex on the right matching i on the left. -1 if not matched 17 | int my[i = 0..mn2-1]: the vertex on the left matching i on the right. -1 if not matched */ 18 | int hungarian(int n1, int n2, int *mx, int *my) { 19 | memset(mx, -1, sizeof(mx[0]) * n1); 20 | memset(my, -1, sizeof(my[0]) * n2); 21 | int ans = 0; 22 | for (int i = 0; i < n1; i++) //use greedy to get an initial matching 23 | for (node *p = g[i]; mx[i] == -1 && p; p = p->next) 24 | if (my[p->v] == -1) mx[i] = p->v, my[p->v] = i, ans++; 25 | static bool vis[mn2]; 26 | for (int i = 0; i < n1 && ans < n1; i++) 27 | if (mx[i] == -1) { 28 | memset(vis, 0, sizeof(vis[0]) * n2); 29 | if (succeed(i, mx, my, vis)) ans++; 30 | } 31 | return ans; 32 | } 33 | -------------------------------------------------------------------------------- /parser/infix-postfix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int precval( char c ) { 4 | if( c == '+' || c == '-' ) return 1; 5 | else return 2; 6 | } 7 | 8 | bool precIsSmaller( char op1, char op2 ) { 9 | return precval( op1 ) < precval( op2 ); 10 | } 11 | 12 | void parse( char *infix, char *postfix ) { 13 | stack s; 14 | char c; 15 | 16 | while( *infix != 0 ) { 17 | switch( *infix ) { 18 | case '(': 19 | s.push( '(' ); 20 | break; 21 | case ')': 22 | while( !s.empty() ) { 23 | c = s.top(); 24 | s.pop(); 25 | if( c == '(') break; 26 | *postfix++ = c; 27 | } 28 | break; 29 | case '+': case '-': case '*': case '/': 30 | while( !s.empty() ) { 31 | c = s.top(); 32 | if( c == '(' ) break; 33 | else if( !precIsSmaller( c, *infix ) ) { 34 | s.pop(); 35 | *postfix++ = c; 36 | } else break; 37 | } 38 | s.push( *infix ); 39 | break; 40 | default: 41 | *postfix++ = *infix; 42 | break; 43 | } 44 | ++infix; 45 | } 46 | 47 | while( !s.empty() ) { 48 | *postfix++ = s.top(); 49 | s.pop(); 50 | } 51 | 52 | *postfix = 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /graphentheorie/ford-fulkerson.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NODES 100 5 | #define INFTY 1000000000 6 | 7 | int nodes, cap[NODES][NODES], flow[NODES][NODES]; 8 | 9 | bool srcside[NODES]; 10 | 11 | struct { 12 | int node, parent, mincap; 13 | } kew[NODES]; 14 | 15 | int low, high; 16 | 17 | int initbfs(int source, int target) { 18 | memset(srcside, 0, sizeof srcside); 19 | srcside[source] = true; 20 | 21 | kew[0].node = source; 22 | kew[0].parent = -1; 23 | kew[0].mincap = INFTY; 24 | 25 | low = 0; 26 | high = 1; 27 | 28 | return target; 29 | } 30 | 31 | bool bfs(int target) { 32 | int from, to; 33 | 34 | while (low < high && (from = kew[low].node) != target) { 35 | for (to = 0; to < nodes; ++to) { 36 | if (!srcside[to] && cap[from][to] > flow[from][to]) { 37 | srcside[to] = true; 38 | 39 | kew[high].node = to; 40 | kew[high].parent = low; 41 | kew[high].mincap = min(kew[low].mincap, cap[from][to] - flow[from][to]); 42 | 43 | ++high; 44 | } 45 | } 46 | 47 | ++low; 48 | } 49 | 50 | return low < high; 51 | } 52 | 53 | int maxflow(int source, int target) { 54 | int i, j, res = 0; 55 | 56 | memset(flow, 0, sizeof flow); 57 | while (bfs(initbfs(source, target))) { 58 | res += kew[low].mincap; 59 | for (i = low; i > 0; i = j) { 60 | j = kew[i].parent; 61 | flow[kew[j].node][kew[i].node] += kew[low].mincap; 62 | flow[kew[i].node][kew[j].node] -= kew[low].mincap; 63 | } 64 | } 65 | 66 | return res; 67 | } 68 | -------------------------------------------------------------------------------- /datenstrukturen/rmq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using std::vector; 3 | 4 | // Wenn Range Maximum Query erwuenscht hier anpassen 5 | inline int min(const int& a, const int& b) {return a < b ? a : b;} 6 | 7 | class rmq 8 | { 9 | int depth, inf; 10 | vector data; 11 | 12 | inline int level(const int& i) {int r = 1; while (i > ((1<(2*i-1, def); 25 | } 26 | void set(const int& index, const int& value) { 27 | int c = (1<= hi(node)) return data[node]; // total hit 40 | else if (from > hi(node) || to < lo(node)) return inf; // total miss 41 | else return min(getmin(from, to, lchild(node)), getmin(from, to, rchild(node))); 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /suchen.tex: -------------------------------------------------------------------------------- 1 | \section{Suchen} 2 | 3 | %\subsection{Bin"are und tern"are Suche} 4 | 5 | %Wenn m"oglich, \lstinline{lower_bound} oder \lstinline{upper_bound} verwenden. 6 | 7 | %Wenn nicht, geht der generelle Algorithmus folgenderma"sen: 8 | %Man braucht ein Pr"adikat (z.B. \lstinline{x < 42}, das irgendwo in dieser Liste 9 | %von \lstinline{true} auf \lstinline{false} springt. Man setzt seine beiden 10 | %Anfangsindizes (z.B. \lstinline{lo} und \lstinline{hi}) auf Werte, von 11 | %denen man sicher wei"s, dass das Pr"adikat an dieses Stellen den jeweiligen 12 | %Wert annimmt. Achtung: Bei Suche in einem Array kann das hei"sen, 13 | %die beiden Startindizes au"serhalb des Arrays zu setzen, z.B. \lstinline{lo = -1} 14 | %und \lstinline{hi = N}. Dann wertet man immer das Pr"adikat beim 15 | %arithmetischen Mittel der beiden Indizes aus und setzt je nach Wert entweder 16 | %\lstinline{lo} oder \lstinline{hi} auf das Mittel. Solange wiederholen, 17 | %bis sich diese beiden Indizes nur noch um eins unterscheiden, dann 18 | %zeigt \lstinline{lo} auf den h"ochsten Wert, wo das Pr"adikat noch 19 | %\lstinline{true} ergibt und \lstinline{hi} auf das niedrigste \lstinline{false}. 20 | % 21 | %Die tern"are Suche eignet sich f"ur bitonische (auf einem Abschnitt monoton 22 | %steigende, auf dem anderen monoton fallende) Funktionen. Immer bei 23 | %einem \emph{und} zwei Dritteln des aktuellen Intervalls auswerten und dann 24 | %nur einen der beiden aktuellen Indizes anpassen. 25 | 26 | %\subsection{N-tes Element (Select)} 27 | 28 | %\lstinputlisting{suchen/select.cpp} 29 | 30 | \subsection{Teilstringsuche (Knuth-Morris-Pratt)} 31 | 32 | \lstinputlisting{suchen/kmp.cpp} 33 | -------------------------------------------------------------------------------- /datenstrukturen.tex: -------------------------------------------------------------------------------- 1 | \section{Datenstrukturen} 2 | 3 | %\subsection{Disjunkte Mengen (Union-Find)} 4 | 5 | %\lstinputlisting{datenstrukturen/disjoint.cpp} 6 | 7 | %\subsection{Heap} 8 | %In der STL gibt es \lstinline{make_heap}, \lstinline{is_heap}, \lstinline{sort_heap}, 9 | %\lstinline{push_heap} und \lstinline{pop_heap}. 10 | %Achtung: Diese Funktionen stellen das \emph{gr"o"ste} Element an die Spitze des Heaps. 11 | % 12 | %\lstinputlisting{datenstrukturen/heap.cpp} 13 | 14 | %\subsection{Fenwick-Baum} 15 | 16 | %\lstinputlisting{datenstrukturen/fenwick.cpp} 17 | 18 | %\subsection{Trie} 19 | 20 | %\subsubsection{Trie mit verketteter Liste} 21 | 22 | %\lstinputlisting{datenstrukturen/trie-list.cpp} 23 | 24 | %\subsubsection{Trie mit Array} 25 | 26 | %\lstinputlisting{datenstrukturen/trie-array.cpp} 27 | 28 | %\subsection{Balancierter bin"arer Suchbaum (AVL)} 29 | 30 | %\lstinputlisting{datenstrukturen/avl.cpp} 31 | 32 | %\subsection{Range Minimum Query (RMQ)} 33 | 34 | %\lstinputlisting{datenstrukturen/rmq.cpp} 35 | 36 | %\subsection{Splay} 37 | 38 | %\lstinputlisting{datenstrukturen/splay.cpp} 39 | 40 | \subsection{STL order statistics tree} 41 | \lstinputlisting{datenstrukturen/stl_rank_select.cpp} 42 | 43 | \subsection{Skew Heaps (meldable priority queue)} 44 | \lstinputlisting{datenstrukturen/SkewHeap.cpp} 45 | 46 | \subsection{Treap} 47 | \lstinputlisting{niklas/treap_simple.cpp} 48 | 49 | \subsection{Fenwick Tree} 50 | \lstinputlisting{niklas/fenwick_tree.cpp} 51 | 52 | \subsection{Segtree} 53 | \lstinputlisting{niklas/segment_tree_skeleton.cpp} 54 | 55 | %\lstinputlisting{niklas/tree_aggregation.cpp} 56 | %\subsection{2D Range Tree} 57 | %\lstinputlisting{datenstrukturen/range_tree.cpp} 58 | 59 | %\subsection{Segment Tree} 60 | %\lstinputlisting{datenstrukturen/Segment_tree.cpp} 61 | -------------------------------------------------------------------------------- /geometrie/old/gerade.cpp: -------------------------------------------------------------------------------- 1 | // Abstand des Punkts pos zum Ursprung 2 | double norm(const vec& a) {return sqrt((a * a).sum());} 3 | 4 | // Abstand zweier Punkte 5 | double dist(const vec& a, const vec& b) {return norm(a - b);} 6 | 7 | // Punkt auf Gerade durch Punkt pos in Richtung dir 8 | // mit kleinstem Abstand zu Ursprung (orthogonale Projektion) 9 | vec proj(const vec& pos, const vec& dir) 10 | {return pos - (pos * dir).sum() / (dir * dir).sum() * dir;} 11 | 12 | // Abstand Punkt-Gerade 13 | double dist(const vec& pos, const vec& dir, const vec& pt) 14 | {return norm(proj(pos - pt, dir));} 15 | 16 | // Schnittpunkt Gerade durch pos in Richtung dir 17 | // mit Gerade/Ebene durch Ursprung mit Normale norm 18 | vec isect(const vec& pos, const vec& dir, const vec& norm) 19 | {return pos - (pos * norm).sum() / (dir * norm).sum() * dir;} 20 | 21 | // 2D-Schnittpunkt der Geraden durch Punkte a1-a2 und b1-b2 22 | vec isect(const vec& a1, const vec& a2, const vec& b1, const vec& b2) { 23 | double temp[] = { a1[1] - a2[1], a2[0] - a1[0] }; 24 | vec norm(temp, 2); 25 | return isect(b1 - a1, b2 - b1, norm) + a1;} 26 | 27 | // Schnittpunkt Gerade durch pos in Richtung dir 28 | // mit Kreis/Kugel um Ursprung mit Radius rad 29 | inline vecvec isect(const vec& pos, const vec& dir, double rad) { 30 | double pp = (pos * pos).sum(), dd = (dir * dir).sum(), 31 | pd = (pos * dir).sum(), rr = rad * rad, 32 | dis = pd * pd - dd * (pp - rr); 33 | 34 | if (dis > EPS) { 35 | vecvec res(pos, 2); 36 | dis = sqrt(dis); 37 | res[0] -= (pd + dis) / dd * dir; 38 | res[1] -= (pd - dis) / dd * dir; 39 | return res; 40 | } else if (dis > -EPS) { 41 | vecvec res(pos, 1); 42 | res[0] -= pd / dd * dir; 43 | return res; 44 | } 45 | 46 | return vecvec(); 47 | } 48 | -------------------------------------------------------------------------------- /geometrie/old/graham.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const long double EPS = 1e-5; 7 | const int MAXPOINTS = 1005; 8 | 9 | struct point { 10 | long double x, y; 11 | } points[MAXPOINTS], hull[MAXPOINTS]; 12 | int npoints, nhull; 13 | 14 | long double signedArea( const point & a, const point & b, const point & c ) { 15 | return a.x * b.y - b.x * a.y + b.x * c.y - c.x * b.y + c.x * a.y - a.x * c.y; 16 | } 17 | 18 | long double sqrdist( const point & a, const point & b ) { 19 | return ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ); 20 | } 21 | 22 | bool bySignedArea( const point & a, const point & b ) { 23 | long double sa = signedArea( points[0], a, b ); 24 | 25 | return ( fabs( sa ) < EPS ) ? 26 | ( sqrdist( points[0], a ) < sqrdist( points[0], b ) ) 27 | : ( sa > 0 ); 28 | } 29 | 30 | void findminpoint( ) { 31 | long double minx = points[0].x, miny = points[0].y; 32 | int currentmin = 0; 33 | 34 | for( int i = 1; i < npoints; ++i ) { 35 | if( points[i].y < miny || ( points[i].y == miny && points[i].x < minx ) ) { 36 | minx = points[i].x; 37 | miny = points[i].y; 38 | currentmin = i; 39 | } 40 | } 41 | 42 | // exchange min point with point[0] 43 | swap( points[currentmin], points[0] ); 44 | } 45 | 46 | void convexhull( ) 47 | { 48 | findminpoint( ); 49 | sort( points + 1, points + npoints, bySignedArea ); 50 | 51 | hull[0] = points[0]; 52 | nhull = 1; 53 | 54 | for( int i = 1; i < npoints; ++i ) { 55 | // hier anpassen, wenn kollineare punkte mit aufgenommen werden sollen 56 | while( nhull > 1 && signedArea( hull[nhull - 2], hull[nhull - 1], points[i] ) < EPS ) { 57 | --nhull; 58 | } 59 | 60 | hull[nhull++] = points[i]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /zahlentheorie.tex: -------------------------------------------------------------------------------- 1 | \section{Zahlentheorie} 2 | 3 | \subsection{Miscellaneous} 4 | \lstinputlisting{niklas/number_theory.cpp} 5 | 6 | \subsection{Binomial Coefficient modulo M} 7 | \lstinputlisting{zahlentheorie/BinomialModK.cpp} 8 | 9 | %\subsection{GGT und Kongruenzen (Euklid)} 10 | 11 | %\lstinputlisting{zahlentheorie/euclid.cpp} 12 | 13 | %\subsection{Chinesischer Restsatz} 14 | 15 | %Zwei Kongruenzen der Art \( x \equiv a_1 \mod m_1,\; x \equiv a_2 \mod m_2 \) 16 | %lassen sich l"osen, indem man jeweils geschickt eine Eins dranmultipliziert und 17 | %das dann aufaddiert. Die erste Kongruenz erweitern wir mit \( m_2^{-1} m_2 \) (Inverses 18 | %bzgl. \(m_1\)) und die zweite mit \(m_1^{-1} m_1\) (bzgl. \(m_2\)). Die Summe 19 | %der rechten Seiten liefert dann das Ergebnis. Die Inversen lassen sich mit dem ggT-Algorithmus von 20 | %Euklid berechnen. 21 | 22 | %Dies funktioniert nur, wenn \(m_1\) und \(m_2\) teilerfremd sind. Wenn nicht, 23 | %muss \( a_1 \equiv a_2 \mod \text{ggT}(m_1, m_2) \) gelten. Dann kann man 24 | %die Kongruenzen durch diesen ggT teilen. 25 | 26 | %\subsection{Eulersche Phi-Funktion} 27 | % 28 | %\(\varphi(n) = \) Anzahl teilerfremde Zahlen kleiner gleich \(n\). 29 | % 30 | %\[ \varphi(n) = n \cdot \prod_{p \mid n, p \text{ prim}} \frac{p-1}{p}, \quad 31 | %m \text{ und } n \text{ teilerfremd } \Longrightarrow\; \varphi(m\cdot n) = 32 | %\varphi(m)\cdot\varphi(n) \text{ und } m^{\varphi(n)} \equiv 1 \mod n \] 33 | % 34 | %Wenn man nur die Werte bis ein paar Millionen braucht, dann mit Backtracking erzeugen: 35 | % 36 | %\lstinputlisting{zahlentheorie/phi.cpp} 37 | 38 | %\subsection{Primzahlen (Erathostenes, Miller-Rabin)} 39 | 40 | %\subsubsection{Sieb des Erathostenes} 41 | 42 | %\lstinputlisting{zahlentheorie/erathostenes.cpp} 43 | 44 | %Fenstersieb? 45 | 46 | %\subsubsection{Primzahltest nach Miller und Rabin} 47 | 48 | %\lstinputlisting{zahlentheorie/miller-rabin.cpp} 49 | -------------------------------------------------------------------------------- /geometrie.tex: -------------------------------------------------------------------------------- 1 | \section{Geometrie} 2 | 3 | %\lstinputlisting{geometrie/old/header.cpp} 4 | 5 | %\subsection{Geraden und Punkte} 6 | 7 | %\lstinputlisting{geometrie/old/gerade.cpp} 8 | 9 | %\subsection{Dreiecke und Liniensegmente} 10 | 11 | %\lstinputlisting{geometrie/old/dreieck.cpp} 12 | %Abstand eines Punktes, Abstand eines anderen Segments. 13 | 14 | %\subsection{Kreise} 15 | 16 | %\lstinputlisting{geometrie/old/kreis.cpp} 17 | %Kreis durch drei Punkte, Kreis durch zwei Punkte mit geg. Radius. 18 | 19 | %\subsection{Polygone} 20 | 21 | %Die \(N\) Punkte eines Polygons werden mit \((x_i,y_i)\) f"ur 22 | %\(i=1,\,\ldots,\,N\) bezeichnet. Konvention: \((x_0,y_0)=(x_N,y_N)\). 23 | 24 | %Die vorzeichenbehaftete Fl"ache \(A\) berechnet sich wie folgt: 25 | %\[ A = \frac{1}{2} \sum_{i=1}^{N} x_{i-1} y_i - x_i y_{i - 1} \] 26 | 27 | %Bei Polygonen mit ganzzahligen Koordinaten gilt f"ur die Fl"ache \(A\), 28 | %die Anzahl der Gitterpunkte auf dem Rand \(B\) und die derjenigen im Innern \(I\): 29 | %\[ I = A - \frac{B}{2} + 1 \] 30 | 31 | %\subsubsection{Punkt in Polygon} 32 | 33 | %\lstinputlisting{geometrie/old/poly-punkt.cpp} 34 | 35 | \subsection{Verschiedenes} 36 | 37 | \lstinputlisting{niklas/geometry.cpp} 38 | 39 | \subsection{Graham's Scan + max. Abstand} 40 | 41 | \lstinputlisting{geometrie/_Modul_Farthestpoints_Graham.cpp} 42 | 43 | %\subsection{3D Konvexe H"ulle} 44 | 45 | %\lstinputlisting{geometrie/3DConvexHull.cpp} 46 | 47 | %\subsection{Kernel of polygon} 48 | 49 | %\lstinputlisting{geometrie/Kernel.cpp} 50 | 51 | %\subsubsection{Clipping an Halbebene bzw. Gerade} 52 | %\lstinputlisting{geometrie/old/clip.cpp} 53 | 54 | % Punkt in konvexem Polygon in O(log n), Clipping an Gerade. (Delaunay-)Triangulation? 55 | 56 | %\subsection{Rasterung von Linien/Kreisen (Bresenham)} 57 | %\lstinputlisting{geometrie/old/bresenham.cpp} 58 | 59 | %\subsection{Sph"arischer Abstand zwischen Punkt und Punkt (Gro"skreis)} 60 | -------------------------------------------------------------------------------- /graphentheorie/scc.cpp: -------------------------------------------------------------------------------- 1 | struct edge {int to; ...} 2 | 3 | // Rueckgabe: jeder vector hat die Knoten in einer SCC 4 | vector > scc(const vector >& graph, const vector >& rgraph) 5 | {// rgraph ist der Graph mit Kanten in umgekehrten Richtung 6 | vector visited(graph.size(), false); 7 | vector done(graph.size(), false); 8 | vector in_order(graph.size(), false); 9 | vector order; 10 | 11 | std::stack s; 12 | for (int start = 0; start < (int)graph.size(); start++) 13 | { 14 | if (visited[start]) continue; 15 | 16 | s.push(start); 17 | while (!s.empty()) 18 | { 19 | int c; 20 | do {c = s.top(); s.pop();} while (!s.empty() && (visited[c] && !done[c])); 21 | if (visited[c] && !done[c]) break; 22 | else visited[c] = true; 23 | 24 | if (done[c] && !in_order[c]) 25 | { 26 | order.push_back(c); 27 | in_order[c] = true; 28 | } 29 | else if (!done[c]) 30 | { 31 | s.push(c); 32 | 33 | for (size_t i = 0; i < graph[c].size(); i++) 34 | if (!visited[graph[c][i].to]) 35 | s.push(graph[c][i].to); 36 | 37 | done[c] = true; 38 | } 39 | } 40 | } 41 | 42 | vector > answer; 43 | 44 | for (size_t i = 0; i < visited.size(); i++) visited[i] = false; 45 | for (int si = (int)order.size()-1; si >= 0; si--) 46 | { 47 | const int& start = order[si]; 48 | 49 | if (visited[start]) continue; 50 | 51 | answer.push_back(vector()); 52 | std::stack s; 53 | s.push(start); visited[start] = true; answer.back().push_back(start); 54 | 55 | while (!s.empty()) 56 | { 57 | int c = s.top(); s.pop(); 58 | 59 | for (size_t i = 0; i < rgraph[c].size(); i++) 60 | if (!visited[rgraph[c][i].to]) 61 | { 62 | visited[rgraph[c][i].to] = true; 63 | s.push(rgraph[c][i].to); 64 | answer.back().push_back(rgraph[c][i].to); 65 | } 66 | } 67 | } 68 | 69 | return answer; 70 | } 71 | -------------------------------------------------------------------------------- /geometrie/old/dreieck.cpp: -------------------------------------------------------------------------------- 1 | // Flaeche des durch a und b aufgespannten Parallelogramms 2 | // positiv, wenn Winkel zwischen a und b positiv 3 | double sgn_area(const vec& a, const vec& b) {return a[0] * b[1] - a[1] * b[0];} 4 | 5 | // positiv, wenn a-b-c im Gegenuhrzeigersinn (math. positiv) liegen 6 | double sgn_area(const vec& a, const vec& b, const vec& c) {return sgn_area(b - a, c - a);} 7 | 8 | // Dreiecksflaeche 9 | double area(const vec& a, const vec& b, const vec& c) {return 0.5 * fabs(sgn_area(a, b, c));} 10 | 11 | // Dreiecksflaeche aus Seitenlaengen 12 | double area(double a, double b, double c) { 13 | if (a < b) swap(a, b); if (b < c) swap(b, c); if (a < b) swap(a, b); 14 | return 0.25 * sqrt((a + (b + c)) * (c - (a - b)) * (c + (a - b)) * (a + (b - c)));} 15 | 16 | // true, wenn a und b verschiedene Vorzeichen haben 17 | inline bool pos_neg(double a, double b) {return (a < 0 && 0 < b) || (b < 0 && 0 < a);} 18 | 19 | // true, wenn Punkt d in Dreieck mit Eckpunkten a-b-c liegt 20 | bool inside(const vec& a, const vec& b, const vec& c, const vec& d) { 21 | double x = sgn_area(c, b, a); 22 | return pos_neg(x, sgn_area(a, b, d)) 23 | && pos_neg(x, sgn_area(b, c, d)) 24 | && pos_neg(x, sgn_area(c, a, d));} 25 | 26 | // true, wenn Punkt c in achsenparallelem Rechteck durch Punkt a und b liegt 27 | bool inside(const vec& a, const vec& b, const vec& c) { 28 | return min(a[0], b[0]) < c[0] + EPS && max(a[0], b[0]) > c[0] - EPS 29 | && min(a[1], b[1]) < c[1] + EPS && max(a[1], b[1]) > c[1] - EPS;} 30 | 31 | // true, wenn c auf Segment a-b liegt bzw. gleich a oder b ist 32 | bool on_seg(const vec& a, const vec& b, const vec& c) { 33 | return inside(a, b, c) && fabs(sgn_area(a, b, c)) < EPS;} 34 | 35 | // Schnitt der Liniensegmente a1-a2 und b1-b2 36 | // 0 = kein Schnitt, 1 = Schnitt, -1 = Beruehrung 37 | int isect(const vec& a1, const vec& a2, const vec& b1, const vec& b2) { 38 | double da1 = sgn_area(b1, b2, a1), da2 = sgn_area(b1, b2, a2), 39 | db1 = sgn_area(a1, a2, b1), db2 = sgn_area(a1, a2, b2); 40 | 41 | if (pos_neg(da1, da2) && pos_neg(db1, db2)) return 1; 42 | if (on_seg(a1, a2, b1) || on_seg(a1, a2, b2) 43 | || on_seg(b1, b2, a1) || on_seg(b1, b2, a2)) return -1; 44 | return 0;} 45 | -------------------------------------------------------------------------------- /graphentheorie/Maxflow_Dinic.cpp: -------------------------------------------------------------------------------- 1 | typedef long long captype; // set capacity type (long long or int) 2 | static const captype flowlimit = 1LL << 60; // should be > maxflow 3 | 4 | struct Dinic { //call init() before use !!! 5 | static const int maxn = 5000, maxm = 30000; 6 | struct edge { 7 | int v, next; 8 | captype c; 9 | bool isrev; 10 | } e[maxm << 1]; 11 | int g[maxn], next[maxn], q[maxn], d[maxn], n, S, T, top; 12 | captype maxflow; 13 | void init(int nn, int SS, int TT) { 14 | n = nn, S = SS, T = TT, top = 0, maxflow = 0; 15 | memset(g, -1, sizeof(g[0]) * n); 16 | } 17 | inline int addedge(int u, int v, captype c) { 18 | e[top] = (edge ) { v, g[u], c, 0 }; 19 | g[u] = top++; 20 | e[top] = (edge ) { u, g[v], 0, 1 }; //undirected: change 0 to c 21 | g[v] = top++; 22 | return top-2; 23 | } 24 | 25 | bool dinicBFS() { 26 | int qh = 0, qt = 1; 27 | memset(d, -1, sizeof(d[0]) * n); 28 | d[q[0] = S] = 0; 29 | while (qh < qt) { 30 | int v = q[qh++]; 31 | for (int p = g[v]; p != -1; p = e[p].next) 32 | if (e[p].c > 0 && d[e[p].v] == -1) 33 | d[e[p].v] = d[v] + 1, q[qt++] = e[p].v; 34 | } 35 | return d[T] >= 0; 36 | } 37 | captype dinicDFS(int v, captype cap) { 38 | if (v == T) return cap; 39 | captype used = 0; 40 | for (int p = next[v]; p != -1 && cap > used; p = e[p].next) { 41 | next[v] = p; 42 | if (e[p].c > 0 && d[e[p].v] == d[v] + 1) { 43 | captype inc = dinicDFS(e[p].v, min(cap - used, e[p].c)); 44 | used += inc; 45 | e[p].c -= inc; 46 | e[p ^ 1].c += inc; 47 | } 48 | } 49 | return used; 50 | } 51 | captype dinic() { 52 | maxflow = 0; 53 | while (dinicBFS()) { 54 | memcpy(next, g, sizeof(g[0]) * n); 55 | maxflow += dinicDFS(S, flowlimit); 56 | } 57 | return maxflow; 58 | } 59 | } dinic; 60 | int main() { 61 | int n, m; 62 | while (scanf("%d%d", &n, &m) != EOF) { 63 | dinic.init(n, 0, n - 1); 64 | int x, y, c; 65 | while (m--) { 66 | scanf("%d%d%d", &x, &y, &c); 67 | dinic.addedge(x, y, c); 68 | } 69 | cout << dinic.dinic() << endl; 70 | for (int i = 0; i < n; ++i) 71 | for (int j = dinic.g[i]; j != -1; j = dinic.e[j].next) 72 | if (dinic.e[j ^ 1].c > 0 && dinic.e[j].isrev == 0) 73 | cout << i << "->" << dinic.e[j].v << " = " << dinic.e[j ^ 1].c << endl; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /graphentheorie/lca_Tarjan.cpp: -------------------------------------------------------------------------------- 1 | // Runtime O(N+Q), offline algorithm. 2 | const int maxn 110000; 3 | struct node { 4 | int data,next,answer; 5 | } edge[maxn],query[maxn]; 6 | int index_edge[maxn],dset[maxn],father[maxn],index_query[maxn]; 7 | int top_edge,top_query; 8 | int tc,n,m,a,b,root; 9 | bool check[maxn]; 10 | void init() { 11 | top_edge = 0, top_query = 0; 12 | memset(index_edge,0,sizeof(index_edge)); 13 | memset(index_query,0,sizeof(index_query)); 14 | memset(father,0,sizeof(father)); 15 | memset(dset,0,sizeof(dset)); 16 | memset(check,0,sizeof(check)); 17 | } // add a tree edge 18 | void add_edge(int u,int v) { 19 | edge[++top_edge].data = v; 20 | edge[top_edge].next = index_edge[u]; 21 | index_edge[u] = top_edge; 22 | } // add a query, each query should be added twice, each time for a node. 23 | void add_query(int u,int v) { 24 | query[++top_query].data = v; 25 | query[top_query].answer = -1; 26 | query[top_query].next = index_query[u]; 27 | index_query[u] = top_query; 28 | } // union-find 29 | int find(int r) { 30 | return dset[r]?dset[r]=find(dset[r]):r; 31 | } // dfs the tree and find the answer for all queries 32 | void dfs(int r) { 33 | int p = index_edge[r]; 34 | while (p!=0) { 35 | dfs(edge[p].data); 36 | dset[find(edge[p].data)] = r; 37 | p = edge[p].next; 38 | } 39 | int q = index_query[r]; 40 | while (q!=0) { 41 | if (check[query[q].data] || query[q].data == r) 42 | query[q].answer = find(query[q].data); 43 | q = query[q].next; 44 | } 45 | check[r] = true; 46 | } 47 | /* If we know the root, the process used to find the root can be deleted and 48 | * the example showed in main() can be simplified. */ 49 | int main() { 50 | init(); 51 | scanf("%d",&n); 52 | for (int i = 1;i= 0; --row) { // eliminate upwards 62 | normalize_row(row, n); 63 | for (int col = 0; col < n; ++col) { 64 | if (M[row][col].zero()) continue; 65 | for (int i = 0; i < row; ++i) { 66 | R a = M[row][col], b = M[i][col]; 67 | for (int k =0; k 0) { 27 | if (p[p.n-1].x == a.x && p[p.n-1].y == a.y) 28 | return; 29 | } 30 | p[p.n++] = a; 31 | } 32 | double sa (point& a, point& b, point& c) { 33 | return (a.x * b.y - a.y * b.x + b.x * c.y - b.y * c.x + c.x * a.y - a.x * c.y) * normalize; 34 | } 35 | point intersect (point& p1, point& p2, point& p3, point& p4) { 36 | double a1 = p2.y - p1.y, b1 = p1.x - p2.x; 37 | double c1 = p1.x*p2.y - p2.x*p1.y; 38 | double a2 = p4.y - p3.y, b2 = p3.x - p4.x; 39 | double c2 = p3.x*p4.y - p4.x*p3.y; 40 | 41 | double d = a1*b2 - a2*b1; 42 | point p; 43 | p.x = (c1*b2 - c2*b1)/d; 44 | p.y = (a1*c2 - a2*c1)/d; 45 | 46 | return p; 47 | } 48 | void doclipping (point& a, point& b, polygon& input, polygon& output) { 49 | output.n = 0; 50 | for (int k = 0; k < input.n; ++k) { 51 | int i = k, ipp = (k+1) % input.n; 52 | double sai = sa (a, b, input[i]); 53 | double saipp = sa (a, b, input[ipp]); 54 | 55 | if (sai >= 0 && saipp >= 0) { 56 | insert (output, input[ipp]); 57 | } else if (sai >= 0 && saipp < 0) { 58 | point c = intersect (a, b, input[i], input[ipp]); 59 | insert (output, c); 60 | } else if (sai < 0 && saipp >= 0) { 61 | point c = intersect (a, b, input[i], input[ipp]); 62 | insert (output, c); 63 | insert (output, input[ipp]); 64 | } else { 65 | assert (sai < 0 && saipp < 0); 66 | } 67 | } 68 | } 69 | int main () { 70 | int currentclipped = 0; 71 | // TODO here: 72 | // input polygon into both poly and clipped[0] !! 73 | 74 | // normalize the direction of the points of the polygon 75 | normalize = signedPolygonArea (poly); 76 | if (normalize > 0) normalize = 1; else normalize = -1; 77 | for (int i = 0; i < poly.n-1; ++i) { 78 | doclipping (poly[i], poly[i+1], clipped[currentclipped], clipped[1-currentclipped]); 79 | currentclipped = 1-currentclipped; 80 | } 81 | doclipping (poly[poly.n-1], poly[0], clipped[currentclipped], clipped[1-currentclipped]); 82 | currentclipped = 1-currentclipped; 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /datenstrukturen/range_tree.cpp: -------------------------------------------------------------------------------- 1 | // space O(n * log n), build O(n * log n), query O(log^2 n + k), k = output 2 | typedef int XX; typedef int YY; 3 | typedef pair Point; 4 | typedef pair > Node; 5 | const XX inf = 1<<30; 6 | 7 | int N; 8 | Node tree[maxn]; 9 | 10 | int left(int i) { return (i<<1) + 1; } 11 | int right(int i) { return (i<<1) + 2; } 12 | bool leaf(int i) { return i >= N-1; } 13 | bool cmpY(const Point& a, const Point& b) { return a.snd < b.snd; } 14 | 15 | void build_rec(vector& src, int l, int r, int i) { 16 | int m = (l+r)/2; 17 | tree[i] = mk(src[m].fst, vector()); 18 | vector& points = tree[i].snd; 19 | if (l == r) { 20 | points = src[l].snd; 21 | } else { 22 | build_rec(src, l, m, left(i)); 23 | build_rec(src, m+1, r, right(i)); 24 | merge(tree[left(i)].snd.begin(), tree[left(i)].snd.end(), 25 | tree[right(i)].snd.begin(), tree[right(i)].snd.end(), 26 | back_inserter(points), cmpY); 27 | } 28 | } 29 | 30 | int cnt; 31 | void report(int n, int y1, int y2) { 32 | vector& p = tree[n].snd; 33 | vector::iterator 34 | l = lower_bound(all(p), Point(0, y1), cmpY), 35 | r = upper_bound(all(p), Point(0, y2), cmpY); 36 | //for (; l != r; ++l) { cout << p.fst<<" "<= tree[n].fst)) 51 | report(n, y1, y2); 52 | } 53 | 54 | void query(int x1, int x2, int y1, int y2) { 55 | int n = 0; 56 | while (!leaf(n)) { // find split point 57 | if (x1 <= tree[n].fst && x2 <= tree[n].fst) n = left(n); 58 | else if (x1 > tree[n].fst && x2 > tree[n].fst) n = right(n); 59 | else break; 60 | } 61 | if (!leaf(n)) { 62 | walk(left(n), x1, y1, y2, true); 63 | walk(right(n), x2, y1, y2, false); 64 | } else if (x1 <= tree[n].fst && tree[n].fst <= x2) { 65 | report(n, y1, y2); 66 | } 67 | } 68 | 69 | void build(vector& src) { 70 | assert(src.size() > 0); 71 | sort(all(src)); 72 | vector items; 73 | items.pb(mk(src[0].fst, vector())); 74 | rep(i,0,src.size()) { 75 | if (i > 0 && src[i-1].fst != src[i].fst) 76 | items.pb(mk(src[i].fst, vector())); 77 | items.back().snd.pb(src[i]); 78 | } 79 | N = 1; 80 | while (N < items.size()) N <<= 1; 81 | while (items.size() < N) items.pb(mk(inf, vector())); 82 | build_rec(items, 0, N-1, 0); 83 | } 84 | -------------------------------------------------------------------------------- /datenstrukturen/avl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | struct avl_t { 3 | avl_t *left, *right, *up; 4 | int height, size, key; 5 | 6 | void reset(); int balance(); avl_t *leftrot(); avl_t *rightrot(); avl_t *fixup(); 7 | avl_t *latch(avl_t *, avl_t *); avl_t *find(int); 8 | avl_t *minimum(); avl_t *maximum(); avl_t *pred(); avl_t *succ(); 9 | }; 10 | inline void avl_t::reset() { 11 | height = max(left != NULL ? left->height + 1 :0, right != NULL ? right->height + 1 :0); 12 | size = 1 + (left != NULL ? left->size : 0) + (right != NULL ? right->size : 0); 13 | } 14 | inline int avl_t::balance() { 15 | return (right != NULL ? right->height + 1 : 0) - (left != NULL ? left->height + 1 : 0); 16 | } 17 | avl_t *avl_t::leftrot() { 18 | avl_t *temp = right; 19 | if ((right = temp->left) != NULL) right->up = this; 20 | temp->left = this; temp->up = up; up = temp; 21 | reset(); temp->reset(); 22 | return temp; 23 | } 24 | avl_t *avl_t::rightrot() { 25 | avl_t *temp = left; 26 | if ((left = temp->right) != NULL) left->up = this; 27 | temp->right = this; temp->up = up; up = temp; 28 | reset(); temp->reset(); 29 | return temp; 30 | } 31 | avl_t *avl_t::fixup() { 32 | int bal = balance(); 33 | if (bal == 2) { 34 | if (right->balance() < 0) right = right->rightrot(); 35 | return leftrot(); 36 | } else if (bal == -2) { 37 | if (left->balance() > 0) left = left->leftrot(); 38 | return rightrot(); 39 | } 40 | return this; 41 | } 42 | avl_t *avl_t::latch(avl_t *root, avl_t *parent) { 43 | if (root == NULL) { left = right = NULL; up = parent; reset(); return this; } 44 | if (key < root->key) root->left = latch(root->left, root); 45 | else if (root->key < key) root->right = latch(root->right, root); 46 | root->reset(); 47 | return root->fixup(); 48 | } 49 | avl_t *avl_t::find(int value) { 50 | avl_t *temp = this; 51 | while (temp != NULL) { 52 | if (value < temp->key) temp = temp->left; 53 | else if (temp->key < value) temp = temp->right; 54 | else return temp; 55 | } 56 | return NULL; 57 | } 58 | avl_t *avl_t::minimum() { 59 | avl_t *temp = this; 60 | while (temp->left != NULL) temp = temp->left; 61 | return temp; 62 | } 63 | avl_t *avl_t::maximum() { 64 | avl_t *temp = this; 65 | while (temp->right != NULL) temp = temp->right; 66 | return temp; 67 | } 68 | avl_t *avl_t::pred() { 69 | avl_t *temp = this; 70 | if (left != NULL) return left->maximum(); 71 | while (temp->up != NULL && temp == temp->up->left) temp = temp->up; 72 | return temp->up; 73 | } 74 | avl_t *avl_t::succ() { 75 | avl_t *temp = this; 76 | if (right != NULL) return right->minimum(); 77 | while (temp->up != NULL && temp == temp->up->right) temp = temp->up; 78 | return temp->up; 79 | } 80 | -------------------------------------------------------------------------------- /graphentheorie/mincostmaxflow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | #define NN 110 7 | int cap[NN][NN]; // adjacency matrix (fill this up) 8 | int cost[NN][NN]; // cost per unit of flow matrix (fill this up) 9 | int fnet[NN][NN], adj[NN][NN], deg[NN]; // flow network and adjacency list 10 | int par[NN], d[NN]; // par[source] = source; // Dijkstra's successor and depth 11 | int pi[NN]; // Labelling function 12 | 13 | #define CLR(a, x) memset( a, x, sizeof( a ) ) 14 | #define Inf (INT_MAX/2) 15 | 16 | // Dijkstra's using non-negative edge weights (cost + potential) 17 | #define Pot(u,v) (d[u] + pi[u] - pi[v]) 18 | bool dijkstra( int n, int s, int t ) 19 | { 20 | for( int i = 0; i < n; i++ ) d[i] = Inf, par[i] = -1; 21 | d[s] = 0; 22 | par[s] = -n - 1; 23 | 24 | while( 1 ) 25 | { 26 | // find u with smallest d[u] 27 | int u = -1, bestD = Inf; 28 | for( int i = 0; i < n; i++ ) if( par[i] < 0 && d[i] < bestD ) 29 | bestD = d[u = i]; 30 | if( bestD == Inf ) break; 31 | 32 | // relax edge (u,i) or (i,u) for all i; 33 | par[u] = -par[u] - 1; 34 | for( int i = 0; i < deg[u]; i++ ) 35 | { 36 | // try undoing edge v->u 37 | int v = adj[u][i]; 38 | if( par[v] >= 0 ) continue; 39 | if( fnet[v][u] && d[v] > Pot(u,v) - cost[v][u] ) 40 | d[v] = Pot( u, v ) - cost[v][u], par[v] = -u-1; 41 | 42 | // try edge u->v 43 | if( fnet[u][v] < cap[u][v] && d[v] > Pot(u,v) + cost[u][v] ) 44 | d[v] = Pot(u,v) + cost[u][v], par[v] = -u - 1; 45 | } 46 | } 47 | 48 | for( int i = 0; i < n; i++ ) if( pi[i] < Inf ) pi[i] += d[i]; 49 | 50 | return par[t] >= 0; 51 | } 52 | #undef Pot 53 | 54 | int mcmf3( int n, int s, int t, int &fcost ) 55 | { 56 | // build the adjacency list 57 | CLR( deg, 0 ); 58 | for( int i = 0; i < n; i++ ) 59 | for( int j = 0; j < n; j++ ) 60 | if( cap[i][j] || cap[j][i] ) adj[i][deg[i]++] = j; 61 | 62 | CLR( fnet, 0 ); 63 | CLR( pi, 0 ); 64 | int flow = 0; 65 | fcost = 0; 66 | 67 | // repeatedly, find a cheapest path from s to t 68 | while( dijkstra( n, s, t ) ) 69 | { 70 | // get the bottleneck capacity 71 | int bot = INT_MAX; 72 | for( int v = t, u = par[v]; v != s; u = par[v = u] ) { 73 | bot = min(bot, fnet[v][u] ? fnet[v][u] : ( cap[u][v] - fnet[u][v] )); 74 | 75 | // update the flow network 76 | for( int v = t, u = par[v]; v != s; u = par[v = u] ) 77 | if( fnet[v][u] ) { fnet[v][u] -= bot; fcost -= bot * cost[v][u]; } 78 | else { fnet[u][v] += bot; fcost += bot * cost[u][v]; } 79 | 80 | flow += bot; 81 | } 82 | 83 | return flow; 84 | } 85 | -------------------------------------------------------------------------------- /graphentheorie.tex: -------------------------------------------------------------------------------- 1 | \section{Graphen} 2 | 3 | % ----------------------------------------------------------------- 4 | %\subsection{Topologische Sortierung} 5 | 6 | %\lstinputlisting{graphentheorie/topo-sort.cpp} 7 | 8 | % ----------------------------------------------------------------- 9 | %\subsection{Starke Zusammenhangskomponenten (Tarjan)} 10 | 11 | %\lstinputlisting{graphentheorie/scc.cpp} 12 | 13 | % ----------------------------------------------------------------- 14 | %\subsection{Eulerscher Kreis} 15 | 16 | %Bei ungerichteten Graphen existiert ein Eulerkreis genau dann, wenn alle Knoten geraden Grad haben. 17 | %Bei gerichteten Graphen existiert ein Eulerkreis genau dann, wenn bei allen Knoten Eingangsgrad und Ausgangsgrad gleich sind. 18 | %Nat"urlich sollte der Graph zusammenh"angend sein! 19 | 20 | %\lstinputlisting{graphentheorie/eulerkreis.cpp} 21 | 22 | % ----------------------------------------------------------------- 23 | %\subsection{K"urzeste Pfade (Dijkstra, Floyd-Warshall, Bellman-Ford)} 24 | 25 | %\subsubsection{Dijkstra} 26 | 27 | %\lstinputlisting{graphentheorie/dijkstra.cpp} 28 | 29 | %\subsubsection{Floyd-Warshall} 30 | 31 | %\lstinputlisting{graphentheorie/floyd-warshall.cpp} 32 | 33 | %\subsubsection{Bellman-Ford} 34 | 35 | %\lstinputlisting{graphentheorie/bellman-ford.cpp} 36 | 37 | % ----------------------------------------------------------------- 38 | %\subsection{Minimaler Spannbaum (Kruskal, Prim)} 39 | 40 | %\subsubsection{Kruskal} 41 | 42 | %\lstinputlisting{graphentheorie/kruskal.cpp} 43 | 44 | %\subsubsection{Prim} 45 | 46 | %\lstinputlisting{graphentheorie/prim.cpp} 47 | 48 | % ----------------------------------------------------------------- 49 | %\subsection{Shortest Path - Dijkstra with heap} 50 | %\lstinputlisting{graphentheorie/dijkstra2.cpp} 51 | 52 | \subsection{Maximum Bipartite Matching} 53 | \lstinputlisting{graphentheorie/BipartiteMatching2.cpp} 54 | 55 | \subsection{Maximaler Fluss (FF + Capacity Scaling)} 56 | \lstinputlisting{graphentheorie/Maxflow_CS.cpp} 57 | 58 | %\subsection{Maximaler Fluss (Dinic)} 59 | %\lstinputlisting{graphentheorie/Maxflow_Dinic.cpp} 60 | % ----------------------------------------------------------------- 61 | 62 | \subsection{Min-Cost-Max-Flow} 63 | %\lstinputlisting{graphentheorie/MincostFlow_SPFA.cpp} 64 | \lstinputlisting{niklas/mincostflow.cpp} 65 | 66 | \subsection{Value of Maximum Matching} 67 | \lstinputlisting{niklas/max_matching.cpp} 68 | 69 | %\subsection{Minimaler Schnitt (Stoer-Wagner)} 70 | %\lstinputlisting{graphentheorie/stoer-wagner.cpp} 71 | 72 | %\subsection{Artikulationspunkte, Br"ucken und Bikonnektivit"at (Tarjan)} 73 | %\lstinputlisting{graphentheorie/Cutnode&Bridge.cpp} 74 | 75 | 76 | %\subsection{Lowest Common Ancestor} 77 | %\lstinputlisting{graphentheorie/lca_Tarjan.cpp} 78 | 79 | \subsection{SCC + 2-SAT} 80 | \lstinputlisting{niklas/2sat.cpp} 81 | 82 | \subsection{LCA} 83 | \lstinputlisting{niklas/lca.cpp} 84 | -------------------------------------------------------------------------------- /graphentheorie/MincostFlow_SPFA.cpp: -------------------------------------------------------------------------------- 1 | typedef long long Captype; // set capacity type (long long or int) 2 | // for Valtype double, replace clr(dis,0x7f) and use epsilon for distance comparison 3 | typedef long long Valtype; // set type of edge weight (long long or int) 4 | static const Captype flowlimit = 1LL<<60; // should be bigger than maxflow 5 | struct MinCostFlow { //XXX Usage: class should be created by new. 6 | static const int maxn = 450; // number of nodes, should be bigger than n 7 | static const int maxm = 5000; // number of edges 8 | struct edge { 9 | int node,next; Captype flow; Valtype value; 10 | } edges[maxm<<1]; 11 | int graph[maxn],queue[maxn],pre[maxn],con[maxn],n,m,source,target,top; 12 | bool inq[maxn]; 13 | Captype maxflow; 14 | Valtype mincost,dis[maxn]; 15 | MinCostFlow() { memset(graph,-1,sizeof(graph)); top = 0; } 16 | inline int inverse(int x) {return 1+((x>>1)<<2)-x; } 17 | inline int addedge(int u,int v,Captype c, Valtype w) { // add a directed edge 18 | edges[top].value = w; edges[top].flow = c; edges[top].node = v; 19 | edges[top].next = graph[u]; graph[u] = top++; 20 | edges[top].value = -w; edges[top].flow = 0; edges[top].node = u; 21 | edges[top].next = graph[v]; graph[v] = top++; 22 | return top-2; 23 | } 24 | bool SPFA() { // Bellmanford, also works with negative edge weight. 25 | int point, nod, now, head = 0, tail = 1; 26 | memset(pre,-1,sizeof(pre)); 27 | memset(inq,0,sizeof(inq)); 28 | memset(dis,0x7f,sizeof(dis)); 29 | dis[source] = 0; queue[0] = source; pre[source] = source; inq[source] = true; 30 | while (head!=tail) { 31 | now = queue[head++]; point = graph[now]; inq[now] = false; head %= maxn; 32 | while (point != -1) { 33 | nod = edges[point].node; 34 | // use epsilon here for floating point comparison to avoid loops 35 | if (edges[point].flow>0 && dis[nod]>dis[now]+edges[point].value) { 36 | dis[nod] = dis[now] + edges[point].value; 37 | pre[nod] = now; 38 | con[nod] = point; 39 | if (!inq[nod]) { 40 | inq[nod] = true; 41 | queue[tail++] = nod; 42 | tail %= maxn; 43 | } 44 | } 45 | point = edges[point].next; 46 | } 47 | } 48 | return pre[target]!=-1; //&& dis[target]<=0; //for min-cost max-flow 49 | } 50 | void extend() 51 | { 52 | Captype w = flowlimit; 53 | for (int u = target; pre[u]!=u; u = pre[u]) 54 | w = min(w, edges[con[u]].flow); 55 | maxflow += w; 56 | mincost += dis[target]*w; 57 | for (int u = target; pre[u]!=u; u = pre[u]) { 58 | edges[con[u]].flow-=w; 59 | edges[inverse(con[u])].flow+=w; 60 | } 61 | } 62 | void mincostflow() { 63 | maxflow = 0; mincost = 0; 64 | while (SPFA()) extend(); 65 | }}; 66 | -------------------------------------------------------------------------------- /graphentheorie/Cutnode&Bridge.cpp: -------------------------------------------------------------------------------- 1 | const int maxn 10010, maxm = 50010; 2 | int ans; 3 | 4 | struct edge { 5 | int data,next; 6 | bool bridge; //if this edge is a bridge 7 | } _dedges[maxm]; 8 | int _dgraph[maxn], _dtp; //adjacency list 9 | int _dc[maxn]; //color of nodes 10 | int _dd[maxn]; //deep of nodes in the DFS tree 11 | int _da[maxn]; //finishing time of visiting nodes 12 | int _dancestor[maxn]; //depth of highest ancestors of node k and its subnodes 13 | int _dstack[maxn]; //save the nodes in a component 14 | bool _dcut[maxn]; //if this node is a cut node 15 | int _dtimer; //time record 16 | int _dtop; //top of stack 17 | int _dcomponent; //number of component 18 | int _droot; //root of the DFS tree 19 | void addedge(int u,int v)//add directed edge, treat undirected edge as 2 directed edges 20 | {_dedges[_dtp].data=v; _dedges[_dtp].next=_dgraph[u]; _dedges[_dtp].bridge=false; _dgraph[u]=_dtp++;} 21 | void init (int DFS_root) { 22 | memset(_dgraph,-1,sizeof(_dgraph)); _dtp = 0; //empty the graph 23 | memset(_dancestor,0x7f,sizeof(_dancestor)); 24 | memset(_dc,0,sizeof(_dc)); 25 | memset(_dcut,0,sizeof(_dcut)); 26 | _dtimer = 0; //the time we've finished visiting a node 27 | _dtop = 0; //empty the stack 28 | _dcomponent = 0; //reset the number of component 29 | _droot = DFS_root; //XXX set the root, make no sense for SCC 30 | } 31 | void DFS(int k, int father, int deep) { 32 | int tot,p,now; 33 | _dc[k] = 1; //state of node, 0 not checked, 1 checking, 2 checked 34 | _dd[k] = deep; //depth of nodes in the DFS tree 35 | // _dancestor[k] = deep, tot = 0; //(1) 36 | // _dstack[_dtop++] = k; //(3) 37 | p = _dgraph[k]; 38 | while (p!=-1) { 39 | now = _dedges[p].data; 40 | if (now != father) {//(1)*** comment this line for Point for SCC (c) 41 | // if (_dc[now] == 1) //(1) 42 | // _dancestor[k] = min(_dancestor[k], _dd[now]); //(1) 43 | }//(1)*** comment this line for Point for SCC (c) ! 44 | if (_dc[now] == 0) { 45 | DFS(now,k,deep+1); 46 | // tot = tot+1, _dancestor[k] = min(_dancestor[k], _dancestor[now]); //(1) 47 | // if ((k==_droot && tot>1) || (k!=_droot && _dancestor[now]>=_dd[k])) //(1) 48 | // _dcut[k] = true; //(1) 49 | // if (_dancestor[now]>_dd[k]) _dedges[p].bridge = true; //(2) 50 | } 51 | p = _dedges[p].next; 52 | } 53 | // if (_dancestor[k]==_dd[k]) { //(3) 54 | // _dcomponent++; //(3) 55 | // do { //(3) 56 | // cout<<_dstack[--_dtop]<b. 4 | const double eps=1e-10, PI=acos(-1.0); 5 | const int mn=3010; 6 | #define mp(A,B) make_pair(A,B) 7 | #define pb(X) push_back(X) 8 | #define clr(x) memset(x,0,sizeof(x)) 9 | struct point{ double x,y; }; 10 | struct polygon { int size; point p[mn]; }; 11 | struct line { point a,b; }; 12 | double at2[mn]; 13 | int ord[mn],dq[mn+1],n; 14 | vector< line > ls; //-> Set of halfplanes, read in here 15 | line tl; 16 | polygon pg; //-> Answer is stored here 17 | // Sign function 18 | inline int sig(double k) { 19 | return (k < -eps)? -1: k > eps; 20 | } // Cross product of vector (p0,p1) and (p0,p2) 21 | inline double multi(point p0, point p1, point p2) { 22 | return ( p1.x - p0.x )*( p2.y - p0.y ) 23 | -( p2.x - p0.x )*( p1.y - p0.y ); 24 | } // Get the intersection point of (s1,e1) and (s2,e2) 25 | void isIntersected(point s1, point e1, point s2, point e2, point &pp) { 26 | double dot1,dot2; 27 | dot1=multi(s2,e1,s1); dot2=multi(e1,e2,s1); 28 | pp.x=(s2.x*dot2 + e2.x*dot1) / (dot2+dot1); 29 | pp.y=(s2.y*dot2 + e2.y*dot1) / (dot2+dot1); 30 | } // Compare function according polar angle in [-PI, PI) 31 | inline bool cmp(int u,int v) { 32 | if(sig(at2[u]-at2[v])==0)return multi(ls[v].a,ls[v].b,ls[u].b)>=0; 33 | return at2[u]2 && sig(pg.p[tmpn-1].x-pg.p[0].x)==0 && 76 | sig(pg.p[tmpn-1].y-pg.p[0].y)==0) tmpn--; 77 | pg.size = tmpn; 78 | } 79 | -------------------------------------------------------------------------------- /geometrie/_Modul_Farthestpoints_Graham.cpp: -------------------------------------------------------------------------------- 1 | /* Runtime: O(n*log(n)). Find 2 farthest points in a set of points. 2 | * Use graham algorithm to get the convex hull. 3 | * Note: In extreme situation, when all points coincide, the program won't work 4 | * probably. A prejudge of this situation may consequently be needed */ 5 | const int mn = 100005; 6 | const double pi = acos(-1.0), eps = 1e-5; 7 | struct point { double x, y; } a[mn]; 8 | int n, cn, st[mn]; 9 | inline bool cmp(const point &a, const point &b) { 10 | if (a.y != b.y) return a.y < b.y; return a.x < b.x; 11 | } 12 | inline int dblcmp(const double &d) { 13 | if (abs(d) < eps) return 0; return d < 0 ? -1 : 1; 14 | } 15 | inline double cross(const point &a, const point &b, const point &c) { 16 | return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); 17 | } 18 | inline double dis(const point &a, const point &b) { 19 | double dx = a.x - b.x, dy = a.y - b.y; 20 | return sqrt(dx * dx + dy * dy); 21 | } // get the convex hull 22 | void graham_scan() { 23 | sort(a, a + n, cmp); 24 | cn = -1; 25 | st[++cn] = 0; 26 | st[++cn] = 1; 27 | for (int i = 2; i < n; i++) { 28 | while (cn>0 && dblcmp(cross(a[st[cn-1]],a[st[cn]],a[i]))<=0) cn--; 29 | st[++cn] = i; 30 | } 31 | int newtop = cn; 32 | for (int i = n - 2; i >= 0; i--) { 33 | while (cn>newtop && dblcmp(cross(a[st[cn-1]],a[st[cn]],a[i]))<=0) cn--; 34 | st[++cn] = i; 35 | } 36 | } 37 | inline int next(int x) { return x + 1 == cn ? 0 : x + 1; } 38 | inline double angle(const point &a,const point &b,const point &c,const point &d){ 39 | double x1 = b.x - a.x, y1 = b.y - a.y, x2 = d.x - c.x, y2 = d.y - c.y; 40 | double tc = (x1 * x2 + y1 * y2) / dis(a, b) / dis(c, d); 41 | return acos(abs(tc) > 1.0 ? (tc > 0 ? 1 : -1) * 1.0 : tc); 42 | } 43 | void maintain(int &p1, int &p2, double &nowh, double &nowd) { 44 | nowd = dis(a[st[p1]], a[st[next(p1)]]); 45 | nowh = cross(a[st[p1]], a[st[next(p1)]], a[st[p2]]) / nowd; 46 | while (1) { 47 | double h = cross(a[st[p1]], a[st[next(p1)]], a[st[next(p2)]]) / nowd; 48 | if (dblcmp(h - nowh) > 0) { 49 | nowh = h; 50 | p2 = next(p2); 51 | } else break; 52 | } 53 | } 54 | double find_max() { 55 | double suma = 0, nowh = 0, nowd = 0, ans = 0; 56 | int p1 = 0, p2 = 1; 57 | maintain(p1, p2, nowh, nowd); 58 | while (dblcmp(suma - pi) <= 0) { 59 | double t1 = angle(a[st[p1]], a[st[next(p1)]], a[st[next(p1)]], 60 | a[st[next(next(p1))]]); 61 | double t2 = angle(a[st[next(p1)]], a[st[p1]], a[st[p2]],a[st[next(p2)]]); 62 | if (dblcmp(t1 - t2) <= 0) { 63 | p1 = next(p1); suma += t1; 64 | } else { 65 | p1 = next(p1); swap(p1, p2); suma += t2; 66 | } 67 | maintain(p1, p2, nowh, nowd); 68 | double d = dis(a[st[p1]], a[st[p2]]); 69 | if (d > ans) ans = d; 70 | } 71 | return ans; 72 | } 73 | int main() { 74 | while (scanf("%d", &n) != EOF && n) { 75 | for (int i = 0; i < n; i++) 76 | scanf("%lf%lf", &a[i].x, &a[i].y); 77 | if (n == 2) 78 | printf("%.2lf\n", dis(a[0], a[1])); 79 | else { 80 | graham_scan(); 81 | double mx = find_max(); 82 | printf("%.2lf\n", mx); 83 | } 84 | } 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /tcr.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper]{article} 2 | 3 | \usepackage{multicol} 4 | \usepackage{booktabs} 5 | 6 | \usepackage[american,ngerman]{babel} 7 | \usepackage{graphicx,subfigure,rotating}\graphicspath{{Figures/}} 8 | \usepackage{amsmath,amsfonts,amssymb,dsfont} 9 | \usepackage{graphicx} 10 | \usepackage{multicol} 11 | \usepackage{tabularx} 12 | \usepackage{amsmath} 13 | \usepackage{pifont} 14 | \usepackage{booktabs} 15 | \usepackage{ltxtable} 16 | \usepackage{inconsolata} %change font here 17 | 18 | % ----------------------------------------------------------------- 19 | % page size and text layout 20 | \usepackage[left=1cm, right=1cm, top=1.5cm, bottom=0.8cm]{geometry} 21 | \setlength{\parindent}{0ex} 22 | \setlength{\parskip}{1ex} 23 | 24 | % ----------------------------------------------------------------- 25 | % encoding and fonts 26 | \usepackage[utf8]{inputenc} 27 | \usepackage[T1]{fontenc} 28 | \usepackage{times} 29 | \usepackage{helvet} 30 | \renewcommand{\familydefault}{\sfdefault} 31 | 32 | % ----------------------------------------------------------------- 33 | % heading 34 | \usepackage{fancyhdr} 35 | \pagestyle{fancy} 36 | \fancyhf{} 37 | \lhead{\bfseries Karlsruhe Institute of Technology} 38 | \rhead{\thepage} 39 | \chead{\leftmark} 40 | 41 | % ----------------------------------------------------------------- 42 | % listings 43 | \usepackage{listings} 44 | \lstset{language=C++} 45 | \lstset{frame=tRBl, frameround=tttt, basicstyle=\footnotesize\ttfamily} 46 | \lstset{numbers=left, numberstyle=\scriptsize} 47 | \lstset{tabsize=4} 48 | 49 | % ----------------------------------------------------------------- 50 | \usepackage{color} 51 | \setcounter{tocdepth}{2} 52 | \definecolor{mylinkcolor}{rgb}{0.5812,0.0665,0.0659} % IndianRed 53 | \definecolor{mycitecolor}{rgb}{0.075,0.31,0.0431} % MossGreen 54 | \definecolor{myurlcolor}{rgb}{0.0118,0.098,0.7412} % DarkBlue 55 | \usepackage[unicode,pdftex,bookmarksdepth,pdfpagelabels,colorlinks,bookmarks=true,bookmarksopen,citecolor = {mycitecolor},linkcolor = {mylinkcolor},urlcolor={myurlcolor},breaklinks=true,hypertexnames=false,hyperindex=true,encap,backref,pagebackref]{hyperref} 56 | 57 | % ----------------------------------------------------------------- 58 | % title information 59 | 60 | \title{ 61 | \includegraphics{Kitlogo_en_cmyk.pdf}\\[1cm] 62 | \Huge \textbf{Team Contest Reference}\\[1cm] 63 | \Large 2016 ACM ICPC Northwestern European Regional Contest\\[1ex] 64 | \Large Bath, November 19-20, 2016\\[2cm] 65 | } 66 | 67 | \author{ 68 | \LARGE Team hacKIT 69 | } 70 | 71 | %\date{\Large \today} 72 | %\date{\today} 73 | \date{} 74 | 75 | % ----------------------------------------------------------------- 76 | % section header spacing 77 | \usepackage[compact]{titlesec} 78 | \titlespacing{\section}{0pt}{0pt}{0pt} 79 | 80 | % ----------------------------------------------------------------- 81 | 82 | % make LaTeX less fussy about line breaking 83 | \sloppy 84 | 85 | % ----------------------------------------------------------------- 86 | \begin{document} 87 | 88 | \maketitle 89 | \thispagestyle{empty} 90 | \newpage 91 | 92 | % ----------------------------------------------------------------- 93 | \setcounter{page}{1} 94 | %\tableofcontents 95 | % \newpage % keine extra seite 96 | 97 | % ----------------------------------------------------------------- 98 | %\input{suchen.tex} 99 | %\input{parser.tex} 100 | \input{stringology.tex} 101 | \input{arithmetik.tex} 102 | %\input{rekurrenzen.tex} 103 | \input{zahlentheorie.tex} 104 | \input{graphentheorie.tex} 105 | \input{geometrie.tex} 106 | \input{datenstrukturen.tex} 107 | \input{dp.tex} 108 | 109 | \input{formulae.tex} 110 | 111 | \end{document} 112 | % ----------------------------------------------------------------- 113 | -------------------------------------------------------------------------------- /arithmetik.tex: -------------------------------------------------------------------------------- 1 | \section{Arithmetik und Algebra} 2 | 3 | %\subsection{Bigints} 4 | 5 | %\subsubsection{Bigints in C++} 6 | 7 | %\lstinputlisting{arithmetik/bigint.cpp} 8 | 9 | %\subsubsection{Bigints in Java} 10 | 11 | %\lstinputlisting{arithmetik/bigint.java} 12 | 13 | %\subsection{Schnelles Potenzieren} 14 | 15 | %\lstinputlisting{arithmetik/potenz.cpp} 16 | 17 | %\subsection{Endliche Summation} 18 | 19 | %Def. Pochhammer-Symbol: \(n^{\underline{k}}=n\cdot(n-1)\cdot\ldots\cdot(n-k+1)\). 20 | %Bei Summation "uber Polynome, dr"ucke die normalen Potenzen in dieser Schreibweise 21 | %aus, z.B. \(3n^2-n=3n^{\underline{2}}+2n^{\underline{1}}\). Dann wie in der Analysis 22 | %integrieren, ergibt eine Art Stammfunktion: 23 | %\[\sum 3n^{\underline{2}}+2n^{\underline{1}} = n^{\underline{3}}+n^{\underline{2}}\] 24 | %Wenn man das Polynom von \(1,\,\ldots,\,N\) summiert, muss man die Stammfunktion 25 | %an der Stelle \(N+1\) und 1 auswerten: 26 | %\[\sum_{n=1}^N 3n^{\underline{2}}+2n^{\underline{1}} 27 | %= n^{\underline{3}}+n^{\underline{2}}\vert_{1}^{N+1} 28 | %= (N+1)^{\underline{3}}+(N+1)^{\underline{2}} = (N+1)N^2\] 29 | % 30 | %Das Gegenteil vom Summationsoperator \(\sum\) ist der Differenzenoperator 31 | %\(\Delta f(x) = f(x+1) - f(x)\). Der e-Funktion entspricht \(2^n\), 32 | %also \(\sum 2^n = \Delta 2^n = 2^n\). 33 | 34 | %\subsection{Matrixmultiplikation (ikj, Strassen)} 35 | 36 | %\subsubsection{Cachefreundliche Matrixmultiplikation} 37 | 38 | %\lstinputlisting{arithmetik/ikj.cpp} 39 | 40 | %\subsubsection{Algorithmus von Strassen} 41 | 42 | %\[ \begin{pmatrix} r & s \\ t & u \end{pmatrix} 43 | %= \begin{pmatrix} a & b \\ c & d \end{pmatrix} 44 | %\begin{pmatrix} e & f \\ g & h \end{pmatrix} \] 45 | % 46 | %\begin{eqnarray}{rcl} 47 | %p_1 & = & a(f-h) \\ 48 | %p_2 & = & (a+b)h \\ 49 | %p_3 & = & (c+d)e \\ 50 | %p_4 & = & d(g-e) \\ 51 | %p_5 & = & (a+d)(e+h) \\ 52 | %p_6 & = & (b-d)(g+h) \\ 53 | %p_7 & = & (a-c)(e+f) 54 | %\end{eqnarray} 55 | % 56 | %Dann: 57 | % 58 | %\[ r = p_5 + p_4 - p_2 + p_6, \quad s = p_1 + p_2, \quad t = p_3 + p_4, \quad u = p_5 + p_1 - p_3 - p_7 \] 59 | 60 | \subsection{Lineare Gleichungssysteme (LGS) und Determinanten} 61 | 62 | \subsubsection{Gau"s-Algorithmus} 63 | 64 | \lstinputlisting{arithmetik/gauss2.cpp} 65 | 66 | \subsubsection{Gau"s-Algorithmus (einfach)} 67 | \lstinputlisting{niklas/gauss.cpp} 68 | 69 | \subsubsection{LR-Zerlegung, Determinanten} 70 | 71 | \lstinputlisting{arithmetik/lr.cpp} 72 | 73 | \subsection{Numerical Integration (Adaptive Simpson's rule)} 74 | 75 | \lstinputlisting{arithmetik/simpson.cpp} 76 | 77 | %\subsection{Polynome} 78 | 79 | %\subsubsection{Newtonsche/Hermitsche Interpolation} 80 | 81 | %Dividierte Differenzen: 82 | %\[ [x_i,\ldots,x_j] = \frac{[x_{i+1},\ldots,x_j] - [x_i,\ldots,x_{j-1}]}{x_j - x_i} \] 83 | %\[ [\underbrace{x_i,\ldots,x_i}_{n \mathrm{mal}}] = f^{(n-1)}(x_i)/n! \] 84 | 85 | %Newton-Polynome: 86 | %\[ P_i = \prod_{k=1}^{i-1} (x-x_k) \] 87 | %Also immer ein Term weniger mulitplizieren als das neue \(x_i\)! 88 | 89 | %Interpoliertes Polynom: 90 | %\[ P = \sum_{i=1}^{n} [x_1,\ldots,x_i] \cdot P_i \] 91 | 92 | %Wenn ein \(x_i\) mehrmals auftaucht, als man auch die ersten paar Ableitungen 93 | %interpolieren will, wird dieses \(x_i\) dann halt auch im Newton-Polynom 94 | %mehrmals dranmultipliziert. 95 | 96 | %\subsubsection{Hornerschema} 97 | 98 | %Seien \(f(T) = \sum_{i = 0}^{n} \alpha_i T^i\) und \(g(T) = \sum_{j = 0}^{m} \beta_j T^j\) zwei Polynome. %Setze f"ur alle \(i = n,\,\ldots,\,0\): 99 | %\[\gamma_i = \alpha_i - 100 | %\sum_{j = \max(1, m - i)}^{\min(m, n - i)} \beta_{m - j} \gamma_{i + j}\] 101 | %Dann ist der Rest \(r(T)\) und das Ergebnis \(s(T)\) der Division von \(f\) durch \(g\) gegeben durch: 102 | %\[r(T) = \sum_{i = 0}^{m - 1} \gamma_i T^i,\quad s(T) 103 | %= \sum_{j = m}^{n} \gamma_j T^{j-m}\] 104 | 105 | % Polynommultiplikation via FFT 106 | \subsection{FFT} 107 | \lstinputlisting{arithmetik/fft.cpp} 108 | -------------------------------------------------------------------------------- /rekurrenzen.tex: -------------------------------------------------------------------------------- 1 | \section{Rekurrenzen, Kombinatorik und DP} 2 | 3 | %\subsection{Lineare Rekurrenzen (z.B. Fibonacci)} 4 | 5 | %Lassen sich als Matrixgleichung schreiben, z.B. Fibonacci: 6 | %\[ \begin{pmatrix} F_n \\ F_{n-1} \end{pmatrix} 7 | %= \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix} 8 | %\cdot \begin{pmatrix} F_{n-1} \\ F_{n-2} \end{pmatrix} \] 9 | %F"ur gro"se \(n\) dann einfach die Matrix mittels 10 | %schneller Potenzierung potenzieren, geht in \(\mathrm O(\log n)\). 11 | 12 | \subsection{Urnenmodelle} 13 | 14 | \begin{tabular}{r||c|c} 15 | \(k\) aus \(n\) ziehen & mit Zur"ucklegen & ohne Zur"ucklegen \\ 16 | \hline 17 | mit Beachtung der Reihenfolge & \(n^k\) & \(\binom{n}{k}\cdot k!\) \\ 18 | \hline 19 | ohne Beachtung der Reihenfolge & \(\binom{n+k-1}{k}\) & \(\binom{n}{k}\) \\ 20 | \end{tabular} 21 | 22 | \subsection{Binomialkoeffizienten} 23 | 24 | \[ \binom{n}{k} = \frac{n!}{k!(n-k)!}, \quad 25 | \binom{n}{k} = \binom{n}{n-k}, \quad 26 | \binom{r}{k} = \frac{r}{k} \binom{r-1}{k-1}, \quad 27 | \binom{r}{k} = \binom{r-1}{k} + \binom{r-1}{k-1} \] 28 | \[ \binom{r}{k} = (-1)^k \binom{k-r-1}{k}, \quad 29 | \binom{r}{m} \binom{m}{k} = \binom{r}{k} \binom{r-k}{m-k}, \quad 30 | (x+y)^r = \sum_{k=0}^r \binom{r}{k} x^k y^{r - k} \] 31 | \[ \sum_{0 \leq k \leq n} \binom{k}{m} = \binom{n+1}{m+1}, \quad 32 | \sum_{k \leq n} \binom{r+k}{k} = \binom{r+n+1}{n}, \quad 33 | \sum_k \binom{r}{k} \binom{s}{n-k} = \binom{r+s}{n} \] 34 | 35 | \subsection{H"aufige Rekurrenzen in der Kombinatorik} 36 | 37 | %\subsubsection{Catalansche Zahlen} 38 | % 39 | %Anzahl der Sehnentriangulationen eines \(n+2\)-Ecks, Anzahl der g"ultigen Klammerausdr"ucke mit \(n%\) Klammern, 40 | %Anzahl der Pfade in einem Grid, wobei man nur eins nach rechts und eins nach unten gehen darf. 41 | %\[ C_n = \frac{1}{n+1} \binom{2n}{n}, \quad C_{n+1} = \sum_{k=0}^{n} C_k C_{n-k} \] 42 | 43 | \subsubsection{Stirlingsche Zahlen} 44 | 45 | \begin{itemize} 46 | \item 1. Art \\ 47 | Anzahl der \(n\)-Permutationen mit genau \(k\) Zyklen. 48 | \[ s_{n+1,k} = s_{n,k-1} + n \cdot s_{n,k} \] 49 | 50 | \item 2. Art \\ 51 | Anzahl der M\"oglichkeiten, genau $k$ nichtleere, paarweise disjunkte Partitionen aus \(n\) Elementen zu bilden. 52 | \[ S_{n+1,k} = S_{n,k-1} + k \cdot S_{n,k} \] 53 | \[ S_{n,k} = \frac{1}{k!} \sum^k_{j=0}(-1)^{k-j}{r \choose j}j^n \] 54 | \end{itemize} 55 | 56 | \subsubsection{Eulersche Zahlen} 57 | 58 | Anzahl der \(n\)-Permutation, wo genau \(k\) Elemente gr"o"ser als ihr 59 | vorhergehendes sind. 60 | \[ E_{n,k} = (n-k) \cdot E_{n-1,k-1} + (k+1) \cdot E_{n-1,k} \] 61 | 62 | %\subsection{Longest Increasing Subsequence} 63 | 64 | %\lstinputlisting{rekurrenzen/lis.cpp} 65 | 66 | %\subsection{\textsc{SUBSET-SUM} (\textsc{KNAPSACK} nur mit Gewichten)} 67 | 68 | %\lstinputlisting{rekurrenzen/subset-sum.cpp} 69 | 70 | \subsection{Nim (bisschen Spieltheorie)} 71 | 72 | Gegeben: \(n\) Haufen mit \(a_1,\ldots,a_n\) Steinen, wer dran ist nimmt bis zu \(k\) Steine von einem Haufen (\(k=\infty\) erlaubt). 73 | 74 | \begin{description} 75 | \item[1. Variante:] Ziel ist es als letztes einen Stein aufzunehmen. Man gewinnt, wenn 76 | \lstinline{(a[1] % (k + 1)) XOR ... XOR (a[n] % (k + 1)) != 0} vor dem eigenen Zug. 77 | \item[2. Variante:] Ziel ist es, dass der Gegner den letztes Stein aufnimmt: 78 | To win at mis\`ere nim, play exactly as if you were playing normal play nim, except if your winning move would 79 | lead to a position that consists of heaps of size one only. In that case, leave exactly one more or one fewer 80 | heaps of size one than the normal play strategy recommends. 81 | \item[3. Variante:] Ziel ist es, den letzten Stein eines der Haufen aufzunehmen. Man gewinnt, wenn 82 | vor dem eigenem Zug ein Stapel maximal \(k\) Steine hat oder 83 | \lstinline{(a[1] % (k + 1)) XOR ... XOR (a[n] % (k + 1)) != 0}, 84 | indem man entweder den letzten Stein nimmt oder man genau diesen Zustand herstellt. 85 | \end{description} 86 | 87 | %\subsection{Optimaler Suchbaum} 88 | %Mit Knuths Verbesserung. 89 | 90 | %max-sum-2d 91 | 92 | %%% Local Variables: 93 | %%% TeX-master: "tcr" 94 | %%% End: 95 | -------------------------------------------------------------------------------- /stringology/suffixarray.cpp: -------------------------------------------------------------------------------- 1 | /* Runtime: Linear 2 | * LCP: Longest Common Prefix. 3 | * S: integer array indicates a string. If the input is characters, 4 | * convert them into integers first. 5 | * SA[i]: i-th suffix of s in alphabet order. 6 | * Rank[i]: rank of suffix starting at position i in alphabet order */ 7 | #include 8 | #include 9 | #define maxn 200010 10 | #define maxl 19 // 1 << (maxl - 1) should be >= maxn 11 | #define EPS 1e-12 12 | int n, s[maxn], SA[maxn], rank[maxn], h[maxn], height[20][maxn]; 13 | inline int max(int a1,int a2) {return a1>a2?a1:a2;} 14 | inline int min(int a1,int a2) {return a1b) a^=b, b^=a, a^=b; 92 | a++; 93 | int delta=(int)(log(b-a+1)/log(2)+EPS); 94 | return min(height[delta][a],height[delta][b-(1<1) suffixArray(s,SA,n,256); else SA[0]=0; // get SA array 101 | Height_RMQ(); 102 | printf("%d\n",LCP(0,1)); // Example 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /geometrie/3DConvexHull.cpp: -------------------------------------------------------------------------------- 1 | // Get convex hull in 3 dimension space. Runtime(n^2) 2 | #include 3 | #include 4 | #include 5 | #define eps 1e-7 6 | #define MAXV 1305 7 | using namespace std; 8 | struct pt{ // point in 3 dimesions 9 | double x, y, z; 10 | pt(){} 11 | pt(double _x, double _y, double _z): x(_x), y(_y), z(_z){} 12 | pt operator-(const pt p1){return pt(x - p1.x, y - p1.y, z - p1.z);} 13 | pt operator*(pt p){return pt(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);} //cross 14 | double operator^(pt p){return x*p.x+y*p.y+z*p.z;} // dot product 15 | }; 16 | struct _3DCH{ 17 | struct fac{ 18 | int a, b, c; //3 points in a face 19 | bool ok; //indicates if this face belongs to the final convex hull. 20 | }; 21 | int n; //initial number of points 22 | pt P[MAXV]; //initial points 23 | int cnt; //number of triangles on the face of convex hull 24 | fac F[MAXV*8]; //triangles on the face of convex hull 25 | int to[MAXV][MAXV]; 26 | double vlen(pt a){return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);} //length of vector 27 | double area(pt a, pt b, pt c){return vlen((b-a)*(c-a));} //2*triangle area 28 | double volume(pt a,pt b,pt c,pt d){return (b-a)*(c-a)^(d-a);}//6*Tetrahedron volume 29 | double ptof(pt &p, fac &f){ //positive if on the same side 30 | pt m = P[f.b]-P[f.a], n = P[f.c]-P[f.a], t = p-P[f.a]; 31 | return (m * n) ^ t; 32 | } 33 | void deal(int p, int a, int b){ 34 | int f = to[a][b]; 35 | fac add; 36 | if (F[f].ok){ 37 | if (ptof(P[p], F[f]) > eps) dfs(p, f); 38 | else { 39 | add.a = b, add.b = a, add.c = p, add.ok = 1; 40 | to[p][b] = to[a][p] = to[b][a] = cnt; 41 | F[cnt++] = add; 42 | } 43 | } 44 | } 45 | void dfs(int p, int cur) { 46 | F[cur].ok = 0; 47 | deal(p, F[cur].b, F[cur].a); 48 | deal(p, F[cur].c, F[cur].b); 49 | deal(p, F[cur].a, F[cur].c); 50 | } 51 | bool same(int s, int t) { 52 | pt &a = P[F[s].a], &b = P[F[s].b], &c = P[F[s].c]; 53 | return fabs(volume(a, b, c, P[F[t].a])) < eps && fabs(volume(a, b, c, 54 | P[F[t].b])) < eps && fabs(volume(a, b, c, P[F[t].c])) < eps; 55 | } 56 | void construct() { // Construct convex hull. It is he method to be called. 57 | cnt = 0; 58 | if (n < 4) return; 59 | /****this code is to make sure the first 4 points are not coplanar, 60 | * can be deleted if it is already garanteed*****/ 61 | bool sb = 1; 62 | for (int i = 1; i < n; i++){ //make sure first 2 points aren't concurrent. 63 | if (vlen(P[0] - P[i]) > eps){ swap(P[1], P[i]); sb = 0; break; }} 64 | if (sb)return; 65 | sb = 1; 66 | for (int i = 2; i < n; i++){ //make sure first 3 points are not colinear. 67 | if (vlen((P[0] - P[1]) * (P[1] - P[i])) > eps) 68 | { swap(P[2], P[i]);sb = 0;break;}} 69 | if (sb)return; 70 | sb = 1; 71 | for (int i = 3; i < n; i++){ //make sure first 4 points are not coplanar. 72 | if (fabs((P[0] - P[1]) * (P[1] - P[2]) ^ (P[0] - P[i])) > eps) 73 | { swap(P[3], P[i]);sb = 0;break;}} 74 | if (sb)return; 75 | /*to make sure the first 4 points are not coplanar, can be deleted(above)*/ 76 | fac add; 77 | for (int i = 0; i < 4; i++){ 78 | add.a = (i+1)%4, add.b = (i+2)%4, add.c = (i+3)%4, add.ok = 1; 79 | if (ptof(P[i], add) > 0) 80 | swap(add.b, add.c); 81 | to[add.a][add.b] = to[add.b][add.c] = to[add.c][add.a] = cnt; 82 | F[cnt++] = add; 83 | } 84 | for (int i = 4; i < n; i++) 85 | for (int j = 0; j < cnt; j++) 86 | if (F[j].ok && ptof(P[i], F[j]) > eps){ 87 | dfs(i, j); 88 | break; 89 | } 90 | int tmp = cnt; 91 | cnt = 0; 92 | for (int i = 0; i < tmp; i++) 93 | if (F[i].ok) F[cnt++] = F[i]; 94 | } 95 | double area() { //surface area 96 | double ret = 0.0; 97 | for (int i = 0; i < cnt; i++) 98 | ret += area(P[F[i].a], P[F[i].b], P[F[i].c]); 99 | return ret / 2.0; 100 | } 101 | double volume() { //volume 102 | pt O(0, 0, 0); 103 | double ret = 0.0; 104 | for (int i = 0; i < cnt; i++) 105 | ret += volume(O, P[F[i].a], P[F[i].b], P[F[i].c]); 106 | return fabs(ret / 6.0); 107 | } 108 | int facetCnt_tri() {return cnt;} //number of triangles on the face. 109 | int facetCnt() { //number of faces. 110 | int ans = 0; 111 | for (int i = 0; i < cnt; i++){ 112 | bool nb = 1; 113 | for (int j = 0; j < i; j++) if (same(i, j)){ nb = 0; break;} 114 | ans += nb; 115 | } 116 | return ans; 117 | } 118 | }; 119 | _3DCH hull; /**Read data in hull.n and hull.p, call hull.construct() **/ -------------------------------------------------------------------------------- /Formulae_gametheory.tex: -------------------------------------------------------------------------------- 1 | \begin{longtable}{l|X|X|X} 2 | \toprule 3 | \multicolumn{4}{c}{Classical Games (\ding{182} last one wins (normal); \ding{183} last one loses (mis\`ere))} \\ \hline 4 | Name & Description & Criteria / Opt.strategy & Remarks \\ \hline 5 | 6 | NIM & $n$ piles of objs. One can take any number of objs from any pile (i.e. set of possible moves for the $i$-th pile is $M=[pile_i]$, $[x]:=\{1,2,...,\lfloor x \rfloor\}$). & $SG=\otimes_{i=1}^n pile_i$. Strategy: \ding{182} make the Nim-Sum 0 by \emph{decreasing} a heap; \ding{183} the same, except when the normal move would only leave heaps of size 1. In that case, leave an odd number of 1's. & The result of \ding{183} is the same as \ding{182}, opposite if all piles are 1's. Many games are essentially NIM.\\ \hline 7 | 8 | NIM (powers) & $M = \{a^m|m\ge 0\}$& If $a$ odd:\newline $SG_n = n \% 2$ & If $a$ even:\newline $SG_n = 2$, if $n\equiv a\%(a+1)$;\newline $SG_n = n \% (a+1) \% 2$, else. \\ \hline 9 | 10 | NIM (half) & $M_{\text{\ding{172}}} = [\frac{pile_i}{2}]$\newline $M_{\text{\ding{173}}} = [\lceil \frac{pile_i}{2} \rceil\text{, } pile_i]$ & \ding{172}$SG_{2n} = n$, $SG_{2n+1}=SG_{n}$\newline \ding{173}$SG_0=0$, $SG_n=[\log_2 n]+1$ & \\ \hline 11 | 12 | NIM (divisors)&$M_{\text{\ding{172}}} = \text{divisors of } pile_i$\newline $M_{\text{\ding{173}}} = \text{proper divisors of }pile_i$ & \ding{172}$SG_0 = 0$, $SG_n = SG_{\text{\ding{173}},n} + 1$ \newline \ding{173}$SG_1=0$, $SG_n=$ number of 0's at the end of $n_{binary}$ \\ \hline 13 | 14 | Subtraction Game & $M_{\text{\ding{172}}} = [k]$\newline $M_{\text{\ding{173}}} = S$ (finite)\newline $M_{\text{\ding{174}}} = S \cup \{pile_i\}$ & $SG_{\text{\ding{172}},n} = n \mod (k+1)$. \ding{182}lose if $SG=0$; \ding{183}lose if $SG=1$. $SG_{\text{\ding{174}},n} = SG_{\text{\ding{173}},n}+1$ & For any finite $M$, $SG$ of one pile is eventually periodic.\\ \hline 15 | 16 | Moore's NIM$_k$ & One can take any number of objs from at most k piles. & \ding{182}Write $pile_i$ in binary, sum up in base $k+1$ without carry. Losing if the result is 0. & \ding{183} If all piles are 1's, losing iff $n\equiv 1\%(k+1)$. Otherwise the result is the same as \ding{182}. \\ \hline 17 | 18 | Staircase NIM & $n$ piles in a line. One can take any number of objs from $pile_i$, $i>0$ to $pile_{i-1}$ & Losing if the NIM formed by the odd-indexed piles is losing(i.e. $\otimes_{i=0}^{(n-1)/2} pile_{2i+1}=0$)\\ \hline 19 | 20 | Lasker's NIM & Two possible moves: 1.take any number of objs; 2.split a pile into two (no obj removed) & $SG_n = n, \text{ if }n\equiv 1,2(\% 4)$\newline $SG_n = n+1, \text{ if }n\equiv3(\% 4)$\newline $SG_n = n-1, \text{ if }n\equiv0(\% 4)$ \\ \hline 21 | 22 | Kayles & Two possible moves: 1.take 1 or 2 objs; 2.split a pile into two (after removing objs) & $SG_n$ for small $n$ can be computed recursively. $SG_n$ for $n \in [72,83]$: 4 1 2 8 1 4 7 2 1 8 2 7 & $SG_n$ becomes periodic from the 72-th item with period length 12. \\ \hline 23 | 24 | Dawson's Chess& $n$ boxes in a line. One can occupy a box if its neighbours are not occupied. & $SG_n$ for $n\in [1,18]$: 1 1 2 0 3 1 1 0 3 3 2 2 4 0 5 2 2 3 & Period = 34 from the 52-th item.\\ \hline 25 | 26 | Wythoff's Game& \textbf{Two} piles of objs. One can take any number of objs from either pile, or take the \emph{same} number from \emph{both} piles.&$n_k = \lfloor k \phi \rfloor = \lfloor m_k \phi \rfloor -m_k$ \newline $m_k = \lfloor k \phi^2 \rfloor = \lceil n_k \phi \rceil = n_k + k$ \newline $\phi:=\frac{1+\sqrt{5}}{2}$. $(n_k,m_k)$ is the $k$-th losing position. & $n_k$ and $m_k$ form a pair of complementary Beatty Sequences (since$\frac{1}{\phi}+\frac{1}{\phi^2}=1$). Every $x>0$ appears either in $n_k$ or in $m_k$.\\ \hline 27 | 28 | Mock Turtles & $n$ coins in a line. One can turn over 1, 2 or 3 coins, with the rightmost from head to tail. & $SG_n = 2n$, if $\mathrm{ones}(2n)$ odd; $SG_n = 2n + 1$, else. $\mathrm{ones}(x)$: the number of 1's in $x_{binary}$ & $SG_n$ for $n\in [0,10]$ (leftmost position is 0): 1 2 4 7 8 11 13 14 16 19 21 \\ \hline 29 | 30 | Ruler & $n$ coins in a line. One can turn over any \emph{consecutive} coins, with the rightmost from head to tail. & $SG_n=$ the largest power of 2 dividing $n$. This is implemented as $n$\&$-n$(lowbit) & $SG_n$ for $n\in [1,10]$: 1 2 1 4 1 2 1 8 1 2\\ \hline 31 | 32 | Hackenbush-tree & Given a forest of rooted trees, one can take an edge and remove the part which becomes unrooted. & At every branch, one can replace the branches by a non-branching stalk of length equal to their nim-sum. & \vtop{\vskip0pt \hbox{\includegraphics[width=4.5cm]{Formulae_gametheory_hackenbush_colon.jpg}}}\\ \hline 33 | 34 | Hackenbush-graph & \vtop{\vskip0pt \hbox{\includegraphics[width=4.5cm]{Formulae_gametheory_hackenbush_graph_example.jpg}}} & Vertices on any circuit can be \emph{fused} without changing SG of the graph. Fusion: two neighbouring vertices into one, and bend the edge into a loop. & \vtop{\vskip0pt \hbox{\includegraphics[width=4.5cm]{Formulae_gametheory_hackenbush_graph_fusion.jpg}}}\\ 35 | 36 | \bottomrule 37 | \end{longtable} -------------------------------------------------------------------------------- /datenstrukturen/Segment_tree.cpp: -------------------------------------------------------------------------------- 1 | #include //hdu 3397, change [a,b] to 0/1, flip [a,b], popcnt([a,b]), longest continuous 1's 2 | #include 3 | using namespace std; 4 | const int maxp = 200005, maxmark = 4, unmarked = 3; 5 | const int trans[maxmark][maxmark] = { { 0, 1, 1, 0 }, { 0, 1, 0, 1 }, { 0, 1,unmarked, 2 }, { 0, 1, 2, unmarked } }; 6 | struct node { 7 | int mark, cnt, cont0, cont0l, cont0r, cont1, cont1l, cont1r; //cnt=number of 1's 8 | node *lc, *rc; 9 | }*root, pool[maxp]; 10 | int pp; 11 | 12 | struct triple { int a, b, c; triple(int x = 0, int y = 0, int z = 0) : a(x), b(y), c(z) {} }; 13 | 14 | void setfields(node *r, int m, int c, int c0, int c0l, int c0r, int c1,int c1l, int c1r) { 15 | r->mark = m; 16 | r->cnt = c; 17 | r->cont0 = c0, r->cont0l = c0l, r->cont0r = c0r; 18 | r->cont1 = c1, r->cont1l = c1l, r->cont1r = c1r; 19 | } 20 | inline void combine_mark(node *r, int m) { r->mark = trans[r->mark][m];} 21 | inline void transmit(node *r, int lr, int rr) { 22 | if (r->lc) combine_mark(r->lc, r->mark); 23 | if (r->rc) combine_mark(r->rc, r->mark); 24 | int s = rr - lr + 1; 25 | switch (r->mark) { 26 | case 0: //set to 0 27 | setfields(r, unmarked, 0, s, s, s, 0, 0, 0); break; 28 | case 1: //set to 1 29 | setfields(r, unmarked, s, 0, 0, 0, s, s, s); break; 30 | case 2: //invert 31 | r->mark = unmarked; 32 | r->cnt = s - r->cnt; 33 | swap(r->cont0, r->cont1); 34 | swap(r->cont0l, r->cont1l); 35 | swap(r->cont0r, r->cont1r); 36 | break; 37 | } 38 | } 39 | void maintain(node *r, int lr, int rr) { 40 | const node &lc = *r->lc, &rc = *r->rc; 41 | int m = (lr + rr) >> 1; 42 | int l1 = m - lr + 1, l2 = rr - m; 43 | if (lc.mark != unmarked) transmit(r->lc, lr, m); 44 | if (rc.mark != unmarked) transmit(r->rc, m + 1, rr); 45 | 46 | r->cnt = lc.cnt + rc.cnt; 47 | r->cont0 = max(max(lc.cont0, rc.cont0), lc.cont0r + rc.cont0l); 48 | r->cont1 = max(max(lc.cont1, rc.cont1), lc.cont1r + rc.cont1l); 49 | r->cont0l = lc.cont0l + (lc.cont0l == l1 ? rc.cont0l : 0); 50 | r->cont1l = lc.cont1l + (lc.cont1l == l1 ? rc.cont1l : 0); 51 | r->cont0r = rc.cont0r + (rc.cont0r == l2 ? lc.cont0r : 0); 52 | r->cont1r = rc.cont1r + (rc.cont1r == l2 ? lc.cont1r : 0); 53 | } 54 | void segtree_build(node *&r, int lr, int rr) { 55 | r = pool + pp++; 56 | setfields(r, unmarked, 0, 0, 0, 0, 0, 0, 0); 57 | r->lc = r->rc = 0; 58 | if (lr == rr) { 59 | scanf("%d", &r->cnt); 60 | r->cont0 = r->cont0l = r->cont0r = !r->cnt; 61 | r->cont1 = r->cont1l = r->cont1r = r->cnt; 62 | } else { 63 | segtree_build(r->lc, lr, (lr + rr) >> 1); 64 | segtree_build(r->rc, ((lr + rr) >> 1) + 1, rr); 65 | maintain(r, lr, rr); 66 | } 67 | } 68 | 69 | void segtree_init(int n) { pp = 0; root = 0; segtree_build(root, 1, n); } 70 | 71 | void segtree_modify(node *r, int lr, int rr, int il, int ir, int op) { 72 | if (r->mark != unmarked) transmit(r, lr, rr); 73 | if (il <= lr && rr <= ir) { r->mark = op;} 74 | else { 75 | int m = (lr + rr) >> 1; 76 | if (il <= m) segtree_modify(r->lc, lr, m, il, ir, op); 77 | if (m < ir) segtree_modify(r->rc, m + 1, rr, il, ir, op); 78 | maintain(r, lr, rr); 79 | } 80 | } 81 | 82 | triple segtree_query(node *r, int lr, int rr, int il, int ir, int op) { 83 | if (r->mark != unmarked) transmit(r, lr, rr); 84 | if (il <= lr && rr <= ir) { 85 | switch (op) { 86 | case 0: return triple(r->cnt); //count 1 87 | case 1: return triple(r->cont1, r->cont1l, r->cont1r); //longest continuous 1's 88 | } 89 | } else { 90 | int m = (lr + rr) >> 1; 91 | triple q1, q2; 92 | if (il <= m) q1 = segtree_query(r->lc, lr, m, il, ir, op); 93 | if (m < ir) q2 = segtree_query(r->rc, m + 1, rr, il, ir, op); 94 | switch (op) { 95 | case 0: return triple(q1.a + q2.a); 96 | case 1: 97 | triple q(max(max(q1.a, q2.a), q1.c + q2.b), q1.b, q2.c); 98 | if (il <= m && ir <= m) q.c = q1.c; 99 | else if (il > m && ir > m) q.b = q2.b; 100 | else if (il <= m && ir > m) { 101 | int l1 = m - max(il, lr) + 1, l2 = min(ir, rr) - m; 102 | if (q.b == l1) q.b += q2.b; 103 | if (q.c == l2) q.c += q1.c; 104 | } 105 | return q; 106 | } 107 | } 108 | return triple(); 109 | } 110 | int main() { 111 | int T, n, m, c, a, b; 112 | triple q; scanf("%d", &T); 113 | while (T--) { 114 | scanf("%d%d", &n, &m); 115 | segtree_init(n); 116 | while (m--) { 117 | scanf("%d%d%d", &c, &a, &b); 118 | ++a, ++b; 119 | switch (c) { 120 | case 0: segtree_modify(root, 1, n, a, b, 0); break;//set to 0 121 | case 1: segtree_modify(root, 1, n, a, b, 1); break;//set to 1 122 | case 2: segtree_modify(root, 1, n, a, b, 2); break;//invert 123 | case 3: q = segtree_query(root, 1, n, a, b, 0); printf("%d\n", q.a); break; //count 1 124 | case 4: q = segtree_query(root, 1, n, a, b, 1); printf("%d\n", q.a); break;//longest 1's 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /arithmetik/bigint.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define LEN 128 5 | #define DPI 9 6 | #define MOD 1000000000 7 | 8 | typedef int bignum[LEN]; 9 | 10 | /* alpha = integ; */ 11 | void set_int(bignum alpha, int integ) { 12 | alpha[0] = 2; 13 | alpha[1] = integ; 14 | } 15 | 16 | /* alpha = atoi(str); */ 17 | void set_str(bignum alpha, char *str) { 18 | char *ptr = str + strlen(str); 19 | int power10, digits = DPI; 20 | 21 | alpha[0] = 1; 22 | while (ptr-- != str) { 23 | if (digits == DPI) { 24 | alpha[alpha[0]++] = 0; 25 | power10 = 1; 26 | digits = 0; 27 | } 28 | 29 | alpha[alpha[0] - 1] += (*ptr - '0') * power10; 30 | power10 *= 10; 31 | ++digits; 32 | } 33 | 34 | while (alpha[0] > 2 && alpha[alpha[0] - 1] == 0) --alpha[0]; 35 | } 36 | 37 | /* alpha = beta; */ 38 | void set_big(bignum alpha, const bignum beta) { 39 | int i; 40 | 41 | for (i = 0; i < beta[0]; ++i) { 42 | alpha[i] = beta[i]; 43 | } 44 | } 45 | 46 | /* alpha += integ; */ 47 | void add_int(bignum alpha, int integ) { 48 | int i = 1; 49 | 50 | while (integ > 0) { 51 | if (i < alpha[0]) integ += alpha[i]; 52 | alpha[i++] = integ % MOD; 53 | integ /= MOD; 54 | } 55 | 56 | if (i > alpha[0]) alpha[0] = i; 57 | } 58 | 59 | /* alpha += beta; */ 60 | void add_big(bignum alpha, const bignum beta) { 61 | int carry = 0, i = 1, j = 1; 62 | 63 | while (carry > 0 || j < beta[0]) { 64 | if (i < alpha[0]) carry += alpha[i]; 65 | if (j < beta[0]) carry += beta[j++]; 66 | alpha[i++] = carry % MOD; 67 | carry /= MOD; 68 | } 69 | 70 | if (i > alpha[0]) alpha[0] = i; 71 | } 72 | 73 | /* alpha -= integ; */ 74 | void sub_int(bignum alpha, int integ) { 75 | int i = 1; 76 | 77 | integ = -integ; 78 | while (integ < 0) { 79 | integ += alpha[i]; 80 | if (integ < 0) integ += 2 * MOD; 81 | alpha[i++] = integ % MOD; 82 | integ /= -MOD; 83 | } 84 | 85 | while (alpha[0] > 2 && alpha[alpha[0] - 1] == 0) --alpha[0]; 86 | } 87 | 88 | /* alpha -= beta; */ 89 | void sub_big(bignum alpha, const bignum beta) { 90 | int carry = 0, i = 1, j = 1; 91 | 92 | while (carry < 0 || j < beta[0]) { 93 | carry += alpha[i]; 94 | if (j < beta[0]) carry -= beta[j++]; 95 | if (carry < 0) carry += 2 * MOD; 96 | alpha[i++] = carry % MOD; 97 | carry /= -MOD; 98 | } 99 | 100 | while (alpha[0] > 2 && alpha[alpha[0] - 1] == 0) --alpha[0]; 101 | } 102 | 103 | /* alpha *= integ; */ 104 | void mul_int(bignum alpha, long long integ) { 105 | long long carry = 0; 106 | int i = 1; 107 | 108 | while (carry > 0 || i < alpha[0]) { 109 | if (i < alpha[0]) carry += alpha[i] * integ; 110 | alpha[i++] = carry % MOD; 111 | carry /= MOD; 112 | } 113 | 114 | if (i > alpha[0]) alpha[0] = i; 115 | } 116 | 117 | /* alpha += beta * gamma; */ 118 | void mul_add(bignum alpha, const bignum beta, const bignum gamma) { 119 | long long integ, carry; 120 | int i, j, k = 1; 121 | 122 | while (k < gamma[0]) { 123 | integ = gamma[k]; 124 | carry = 0; 125 | i = k++; 126 | j = 1; 127 | 128 | while (carry > 0 || j < beta[0]) { 129 | if (i < alpha[0]) carry += alpha[i]; 130 | if (j < beta[0]) carry += beta[j++] * integ; 131 | alpha[i++] = carry % MOD; 132 | carry /= MOD; 133 | } 134 | 135 | if (i > alpha[0]) alpha[0] = i; 136 | } 137 | 138 | while (alpha[0] > 2 && alpha[alpha[0] - 1] == 0) --alpha[0]; 139 | } 140 | 141 | /* alpha *= beta; */ 142 | void mul_big(bignum alpha, const bignum beta) { 143 | bignum gamma; 144 | 145 | set_int(gamma, 0); 146 | mul_add(gamma, alpha, beta); 147 | set_big(alpha, gamma); 148 | } 149 | 150 | /* alpha /= integ; return alpha % integ; */ 151 | int div_int(bignum alpha, int integ) { 152 | long long carry = 0; 153 | int i = alpha[0]; 154 | 155 | while (i > 1) { 156 | carry *= MOD; 157 | carry += alpha[--i]; 158 | alpha[i] = carry / integ; 159 | carry %= integ; 160 | } 161 | 162 | while (alpha[0] > 2 && alpha[alpha[0] - 1] == 0) --alpha[0]; 163 | 164 | return carry; 165 | } 166 | 167 | /* alpha = pow(alpha, integ); */ 168 | void pow_int(bignum alpha, int integ) { 169 | bignum square[2], answer[2]; 170 | int square_idx = 0, answer_idx = 0; 171 | 172 | set_int(answer[answer_idx], 1); 173 | set_big(square[square_idx], alpha); 174 | 175 | while (integ > 0) { 176 | if ((integ & 1)) { 177 | set_int(answer[answer_idx ^ 1], 0); 178 | mul_add(answer[answer_idx ^ 1], answer[answer_idx], square[square_idx]); 179 | answer_idx ^= 1; 180 | } 181 | integ >>= 1; 182 | 183 | set_int(square[square_idx ^ 1], 0); 184 | mul_add(square[square_idx ^ 1], square[square_idx], square[square_idx]); 185 | square_idx ^= 1; 186 | } 187 | 188 | set_big(alpha, answer[answer_idx]); 189 | } 190 | 191 | /* cout << alpha; */ 192 | void print_big(bignum alpha) { 193 | int i = alpha[0] - 1; 194 | 195 | cout << alpha[i]; 196 | cout.fill('0'); 197 | while (i-- > 1) { 198 | cout.width(DPI); 199 | cout << alpha[i]; 200 | } 201 | cout.fill(); 202 | } 203 | -------------------------------------------------------------------------------- /zahlentheorie/NumberTheory.cpp: -------------------------------------------------------------------------------- 1 | typedef unsigned long long ULL; 2 | typedef long long LL; 3 | typedef map factors; 4 | 5 | LL MultiplyMod(LL a, LL b, LL mod) { //computes a * b % mod 6 | ULL r = 0; 7 | a %= mod, b %= mod; 8 | while (b) { 9 | if (b & 1) r = (r + a) % mod; 10 | b >>= 1, a = ((ULL) a << 1) % mod; 11 | } 12 | return r; 13 | } 14 | template 15 | T PowerMod(T a, T n, T mod) { //computes a^n % mod 16 | T r = 1; 17 | while (n) { 18 | if (n & 1) r = MultiplyMod(r, a, mod); 19 | n >>= 1, a = MultiplyMod(a, a, mod); 20 | } 21 | return r; 22 | } 23 | template 24 | bool isprime(T n) { //determines if n is a prime number 25 | const int pn = 9, p[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23 }; 26 | for (int i = 0; i < pn; ++i) 27 | if (n % p[i] == 0) return n == p[i]; 28 | if (n < p[pn - 1]) return 0; 29 | T s = 0, t = n - 1; 30 | while (~t & 1) 31 | t >>= 1, ++s; 32 | for (int i = 0; i < pn; ++i) { 33 | T pt = PowerMod (p[i], t, n); 34 | if (pt == 1) continue; 35 | bool ok = 0; 36 | for (int j = 0; j < s && !ok; ++j) { 37 | if (pt == n - 1) ok = 1; 38 | pt = MultiplyMod(pt, pt, n); 39 | } 40 | if (!ok) return 0; 41 | } 42 | return 1; 43 | } 44 | template 45 | T GCD(T a, T b) { 46 | T r; 47 | while (b) 48 | r = a % b, a = b, b = r; 49 | return a; 50 | } 51 | template 52 | T _pollard_rho(T N) { 53 | if (isprime (N)) return N; 54 | int c = 2; 55 | do { 56 | T x = rand(), y = (x * x + c) % N, d = 1; 57 | int pow = 1, len = 1; 58 | while (1) { 59 | if (len++ == pow) x = y, pow <<= 1, len = 0; 60 | y = (MultiplyMod(y, y, N) + c) % N; 61 | if (x == y) break; 62 | d = GCD ((x > y ? x - y : y - x), N); 63 | if (d != 1) return d; 64 | } 65 | do 66 | c = rand(); 67 | while (c == 0); 68 | } while (1); 69 | return 0; 70 | } 71 | 72 | template 73 | void _factor_large(T N, factors &facts, short exp) { 74 | if (N == 1) return; 75 | T f = _pollard_rho (N); 76 | if (f == N) { 77 | facts[f] += exp; 78 | return; 79 | } 80 | short c = 0; 81 | while (N % f == 0) 82 | N /= f, ++c; 83 | _factor_large(f, facts, exp * c); 84 | _factor_large(N, facts, exp); 85 | } 86 | int getprimes(int *pr, int maxp) { 87 | int mr = maxp * 20; 88 | bool *isp = new bool[mr]; 89 | memset(isp, 1, mr); 90 | for (int i = 2; i * i < mr; ++i) 91 | if (isp[i]) { 92 | for (int j = i * i; j < mr; j += i) 93 | isp[j] = 0; 94 | } 95 | int c = 0; 96 | for (int i = 2; i < mr && c < maxp; ++i) 97 | if (isp[i]) pr[c++] = i; 98 | delete[] isp; 99 | return c; 100 | } 101 | template 102 | void factor(T N, factors &facts) { //factors N into prime factors in facts 103 | const int mp = 100; 104 | static int pr[mp], pn = -1; 105 | if (pn == -1) pn = getprimes(pr, mp); 106 | for (int i = 0; i < pn; ++i) 107 | if (N % pr[i] == 0) { 108 | short c = 0; 109 | while (N % pr[i] == 0) 110 | N /= pr[i], ++c; 111 | facts[pr[i]] += c; 112 | } 113 | _factor_large (N, facts, 1); 114 | } 115 | // calculate d = gcd(a, b), and x,y so that a x + b y = d 116 | template 117 | T ex_gcd(T a, T b, T &x, T &y) { 118 | T q, r, x1 = 0, y1 = 1, x2, y2; 119 | x = 1, y = 0; 120 | while (b) { 121 | q = a / b, r = a % b; 122 | x2 = x - q * x1, y2 = y - q * y1; 123 | a = b, b = r, x = x1, x1 = x2, y = y1, y1 = y2; 124 | } 125 | return a; 126 | } 127 | // solve the linear congruence equation: a x == b (mod n) 128 | // the number of solutions up to congruence (can be 0). 129 | // sol: the minimal positive solution 130 | // dis: the distance between solutions 131 | template 132 | T LinearMod(T a, T b, T n, T &sol, T &dis) { 133 | a = (a % n + n) % n, b = (b % n + n) % n; 134 | T d, x, y; 135 | d = ex_gcd (a, n, x, y); 136 | if (b % d) return 0; 137 | x = (x % n + n) % n; 138 | x = MultiplyMod(b / d, x, n); //use normal mult instead if T = int 139 | dis = n / d; 140 | sol = x % dis; 141 | return d; 142 | } 143 | 144 | // find x. a[i] x = b[i] (mod m[i]) 0 <= i < n. m[i] need not be coprime 145 | template 146 | bool ChineseRemainderTheorem(int n, T *a, T *b, T *m, T &sol, T &mod) { 147 | T A = 1, B = 0, ta, tm, tsol, tdis; 148 | for (int i = 0; i < n; ++i) { 149 | if (!LinearMod (a[i], b[i], m[i], tsol, tdis)) return 0; 150 | ta = tsol, tm = tdis; 151 | if (!LinearMod (A, ta - B, tm, tsol, tdis)) return 0; 152 | B = A * tsol + B; 153 | A = A * tdis; 154 | } 155 | sol = B, mod = A; 156 | return 1; 157 | } 158 | // compute p(n,k), the number of possibilities to write n as a sum of 159 | // k non-zero integers 160 | ll NrPartitions(int n, int k) { 161 | if (n==k) return 1; 162 | if (n powers; // should compute this only once per g 188 | rep(j,0,m) powers[powmod(g, j)] = j; 189 | ll gm = powmod(g, -m + 2*(p-1)); 190 | rep(i,0,m) { 191 | if (contains(powers, b)) return i*m + powers[b]; 192 | b = b * gm % p; 193 | } 194 | assert(0); return -1; 195 | } 196 | -------------------------------------------------------------------------------- /datenstrukturen/splay.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define maxn 610000 4 | #define NEGATIVE_VALUE_INF 1<<31 5 | #define POSITIVE_VALUE_INF 0x7fffffff 6 | struct node { 7 | int ch[2],father; int data,size; int sum,add,dmax,mask; 8 | bool rev,clr; 9 | } sp[maxn]; //sp[0] is sentinel 10 | int top; 11 | struct Splay { 12 | int root; 13 | /*************** fundamental code ***************/ 14 | Splay() { // constructor 15 | root = newnode(NEGATIVE_VALUE_INF); 16 | sp[root].ch[1] = newnode(POSITIVE_VALUE_INF); 17 | sp[sp[root].ch[1]].father = root; //2 special nodes indicate boundary 18 | push_up(root); 19 | } // another construct, called by split(), can be delete when not necessary. 20 | Splay(int add_r) { 21 | root = newnode(NEGATIVE_VALUE_INF); 22 | sp[root].ch[1] = newnode(POSITIVE_VALUE_INF); 23 | sp[sp[root].ch[1]].father = root; 24 | sp[sp[root].ch[1]].ch[0] = add_r; 25 | sp[add_r].father = sp[root].ch[1]; 26 | push_up(sp[root].ch[1]); 27 | push_up(root); 28 | } //return the index of the pos-th element or 0 if it doesn't exist. 29 | int select(int pos) { 30 | if (pos<1 || pos>sp[root].size) return 0; 31 | int res = root; 32 | push_down(root); 33 | while (sp[sp[res].ch[0]].size+1!=pos) { 34 | if (pos>sp[sp[res].ch[0]].size) { 35 | pos-=sp[sp[res].ch[0]].size+1; 36 | res = sp[res].ch[1]; 37 | } else res = sp[res].ch[0]; 38 | push_down(res); 39 | } 40 | return res; 41 | } //right rotate if op==0 or left rotate otherwise. 42 | void rotate(int r, int op) { 43 | int pre = sp[r].father; 44 | push_down(pre); push_down(r); 45 | sp[pre].ch[op] = sp[r].ch[!op]; 46 | sp[sp[r].ch[!op]].father = pre; 47 | sp[r].ch[!op]=pre; 48 | sp[r].father = sp[pre].father; 49 | sp[pre].father = r; 50 | sp[sp[r].father].ch[pre==sp[sp[r].father].ch[1]]=r; 51 | push_up(pre); 52 | } //lift the given node beneath the node goal. Lift to root if goal==0. 53 | void splay(int r, int goal) { 54 | push_down(r); 55 | while (sp[r].father!=goal) { 56 | if (sp[sp[r].father].father==goal) 57 | rotate(r, sp[sp[r].father].ch[1]==r); 58 | else { 59 | int y = sp[r].father, z = sp[y].father, f = (sp[z].ch[1] == y); 60 | if(sp[y].ch[f] == r) { 61 | rotate(y, f); rotate(r, f); 62 | } else { 63 | rotate(r, !f); rotate(r, f); 64 | } 65 | } 66 | } 67 | push_up(r); 68 | if (goal == 0) root = r; 69 | } //select the pos-th node and lift it beneath the node goal. 70 | void lift(int pos,int goal) { 71 | int np = select(pos+1); //be careful with the index 72 | if (np==0) return; 73 | splay(np,goal); 74 | } 75 | /**** functions over ordered structure, can be deleted if not necessary ****/ 76 | int order_find(int data, int &rank) { // binary-search a element 77 | int add = root, res = 0; 78 | push_down(root); 79 | rank = 0; 80 | while (add!=0) { 81 | if (data == sp[add].data) res = add; 82 | if (data >= sp[add].data) { 83 | rank += sp[sp[add].ch[0]].size+1; 84 | add = sp[add].ch[1]; 85 | } else add = sp[add].ch[0]; 86 | if (add!=0) push_down(add); 87 | } 88 | rank--; 89 | return res; 90 | } 91 | void order_remove(int data) { // remove an element 92 | int rank; 93 | if (order_find(data,rank) != 0) 94 | split(rank,rank); 95 | } 96 | void order_insert(int data) { // insert an element 97 | int rank; 98 | order_find(data,rank); 99 | int temp[1]; temp[0] = data; 100 | insert(rank,temp,0,0); 101 | } 102 | /***functions for interval-maintenances in sequence, add them if necessary*/ 103 | int maketree(int *num, int s, int t) { // build a tree from num[s] to num[t] 104 | int m = (s+t) >> 1; 105 | int res = newnode(*(num+m)); 106 | if (slift(0,0); 130 | p->lift(sp[p->root].size-1,p->root); 131 | int r = sp[sp[p->root].ch[1]].ch[0]; 132 | sp[sp[root].ch[1]].ch[0] = r; 133 | sp[r].father = sp[root].ch[1]; 134 | push_up(sp[root].ch[1]); 135 | push_up(root); 136 | } // split all numbers in interval [s, t] and return as a new splay 137 | Splay *split(int s, int t) { 138 | lift(s-1, 0); 139 | lift(t+1, root); 140 | int r = sp[sp[root].ch[1]].ch[0]; 141 | sp[sp[root].ch[1]].ch[0] = 0; 142 | sp[r].father = 0; 143 | push_up(sp[root].ch[1]); 144 | push_up(root); 145 | return new Splay(r); 146 | } 147 | /**** Operations/Queries, add or modify them according to problem **/ 148 | int get_sum(int s, int t) { // get sum of numbers in interval [s, t] 149 | lift(s-1, 0); 150 | lift(t+1, root); 151 | int r = sp[sp[root].ch[1]].ch[0]; 152 | return sp[r].sum; 153 | } // get maximum in interval [s, t] 154 | int get_max(int s, int t) { 155 | lift(s-1, 0); 156 | lift(t+1, root); 157 | int r = sp[sp[root].ch[1]].ch[0]; 158 | return sp[r].dmax; 159 | } // add all numbers in [s, t] with delta 160 | void opt_add(int s, int t, int delta) { 161 | lift(s-1, 0); 162 | lift(t+1, root); 163 | int x = sp[sp[root].ch[1]].ch[0]; 164 | if (sp[x].clr) 165 | sp[x].mask+=delta; 166 | else 167 | sp[x].add += delta; 168 | sp[x].data += delta; 169 | sp[x].sum += delta*sp[x].size; 170 | sp[x].dmax += delta; 171 | push_up(sp[root].ch[1]); 172 | push_up(root); 173 | } // change all numbers in [s, t] with delta 174 | void opt_clr(int s,int t,int delta) { 175 | lift(s-1,0); 176 | lift(t+1,root); 177 | int x = sp[sp[root].ch[1]].ch[0]; 178 | sp[x].add = 0; 179 | sp[x].clr = true; 180 | sp[x].mask = delta; 181 | sp[x].data = delta; 182 | sp[x].sum = delta*sp[x].size; 183 | sp[x].dmax = delta; 184 | push_up(sp[root].ch[1]); 185 | push_up(root); 186 | } // reverse all numbers in [s, t] 187 | void opt_rev(int s,int t) { 188 | lift(s-1, 0); 189 | lift(t+1, root); 190 | int x = sp[sp[root].ch[1]].ch[0]; 191 | sp[x].rev ^= 1; 192 | swap(sp[x].ch[0],sp[x].ch[1]); 193 | } 194 | /**** Basic functions. Modify the fields of nodes according to problem ****/ 195 | int newnode(int d) { // generate a new node 196 | ++top; 197 | sp[top].father = sp[top].ch[0] = sp[top].ch[1] = 0; 198 | sp[top].data = d; 199 | sp[top].add = 0; 200 | sp[top].rev = false; 201 | sp[top].clr = false; 202 | push_up(top); 203 | return top; 204 | } // handle the marks and maintain data downward 205 | void push_down(int r) { 206 | for (int i=0;i<2;++i) { //be careful with interaction of multiple marks 207 | int x = sp[r].ch[i]; 208 | if (x==0) continue; 209 | if (sp[r].add!=0) {//mark ADD 210 | if (sp[x].clr) 211 | sp[x].mask+=sp[r].add; 212 | else 213 | sp[x].add+=sp[r].add; 214 | sp[x].data+=sp[r].add; 215 | sp[x].sum+=sp[r].add*sp[x].size; 216 | sp[x].dmax+=sp[r].add; 217 | } 218 | if (sp[r].clr) {//CLEAR 219 | sp[x].clr = 1; 220 | sp[x].mask = sp[r].mask; 221 | sp[x].add = 0; 222 | sp[x].data = sp[r].mask; 223 | sp[x].sum = sp[r].mask*sp[x].size; 224 | sp[x].dmax = sp[r].mask; 225 | } 226 | if (sp[r].rev) { //REVERSE 227 | sp[x].rev^=1; 228 | swap(sp[x].ch[0],sp[x].ch[1]); 229 | } 230 | } 231 | sp[r].add = 0; 232 | sp[r].clr = false; 233 | sp[r].rev = false; 234 | } // maintain data upward 235 | void push_up(int r) { 236 | sp[r].size = 1 + sp[sp[r].ch[0]].size + sp[sp[r].ch[1]].size; 237 | sp[r].sum = sp[r].data+sp[sp[r].ch[0]].sum+sp[sp[r].ch[1]].sum; 238 | sp[r].dmax = max(sp[r].data, 239 | max(sp[sp[r].ch[0]].dmax, sp[sp[r].ch[1]].dmax)); 240 | } 241 | }; 242 | void init() { // initalize the memory pool and some data 243 | top = 0; 244 | sp[0].dmax = NEGATIVE_VALUE_INF; //sp[0] is sentinel 245 | } -------------------------------------------------------------------------------- /formulae/Formulae.log: -------------------------------------------------------------------------------- 1 | This is pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6) (format=pdflatex 2010.11.13) 16 NOV 2010 14:26 2 | entering extended mode 3 | %&-line parsing enabled. 4 | **Formulae.tex 5 | (./Formulae.tex 6 | LaTeX2e <2005/12/01> 7 | Babel and hyphenation patterns for english, usenglishmax, dumylang, noh 8 | yphenation, arabic, basque, bulgarian, coptic, welsh, czech, slovak, german, ng 9 | erman, danish, esperanto, spanish, catalan, galician, estonian, farsi, finnish, 10 | french, greek, monogreek, ancientgreek, croatian, hungarian, interlingua, ibyc 11 | us, indonesian, icelandic, italian, latin, mongolian, dutch, norsk, polish, por 12 | tuguese, pinyin, romanian, russian, slovenian, uppersorbian, serbian, swedish, 13 | turkish, ukenglish, ukrainian, loaded. 14 | (/usr/share/texmf/tex/latex/base/article.cls 15 | Document Class: article 2005/09/16 v1.4f Standard LaTeX document class 16 | (/usr/share/texmf/tex/latex/base/size10.clo 17 | File: size10.clo 2005/09/16 v1.4f Standard LaTeX file (size option) 18 | ) 19 | \c@part=\count79 20 | \c@section=\count80 21 | \c@subsection=\count81 22 | \c@subsubsection=\count82 23 | \c@paragraph=\count83 24 | \c@subparagraph=\count84 25 | \c@figure=\count85 26 | \c@table=\count86 27 | \abovecaptionskip=\skip41 28 | \belowcaptionskip=\skip42 29 | \bibindent=\dimen102 30 | ) 31 | (/usr/share/texmf/tex/latex/graphics/graphicx.sty 32 | Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR) 33 | 34 | (/usr/share/texmf/tex/latex/graphics/keyval.sty 35 | Package: keyval 1999/03/16 v1.13 key=value parser (DPC) 36 | \KV@toks@=\toks14 37 | ) 38 | (/usr/share/texmf/tex/latex/graphics/graphics.sty 39 | Package: graphics 2006/02/20 v1.0o Standard LaTeX Graphics (DPC,SPQR) 40 | 41 | (/usr/share/texmf/tex/latex/graphics/trig.sty 42 | Package: trig 1999/03/16 v1.09 sin cos tan (DPC) 43 | ) 44 | (/usr/share/texmf/tex/latex/config/graphics.cfg 45 | File: graphics.cfg 2007/01/18 v1.5 graphics configuration of teTeX/TeXLive 46 | ) 47 | Package graphics Info: Driver file: pdftex.def on input line 90. 48 | 49 | (/usr/share/texmf/tex/latex/pdftex-def/pdftex.def 50 | File: pdftex.def 2007/01/08 v0.04d Graphics/color for pdfTeX 51 | \Gread@gobject=\count87 52 | )) 53 | \Gin@req@height=\dimen103 54 | \Gin@req@width=\dimen104 55 | ) 56 | (/usr/share/texmf/tex/latex/tools/multicol.sty 57 | Package: multicol 2006/05/18 v1.6g multicolumn formatting (FMi) 58 | \c@tracingmulticols=\count88 59 | \mult@box=\box26 60 | \multicol@leftmargin=\dimen105 61 | \c@unbalance=\count89 62 | \c@collectmore=\count90 63 | \doublecol@number=\count91 64 | \multicoltolerance=\count92 65 | \multicolpretolerance=\count93 66 | \full@width=\dimen106 67 | \page@free=\dimen107 68 | \premulticols=\dimen108 69 | \postmulticols=\dimen109 70 | \multicolsep=\skip43 71 | \multicolbaselineskip=\skip44 72 | \partial@page=\box27 73 | \last@line=\box28 74 | \mult@rightbox=\box29 75 | \mult@grightbox=\box30 76 | \mult@gfirstbox=\box31 77 | \mult@firstbox=\box32 78 | \@tempa=\box33 79 | \@tempa=\box34 80 | \@tempa=\box35 81 | \@tempa=\box36 82 | \@tempa=\box37 83 | \@tempa=\box38 84 | \@tempa=\box39 85 | \@tempa=\box40 86 | \@tempa=\box41 87 | \@tempa=\box42 88 | \@tempa=\box43 89 | \@tempa=\box44 90 | \@tempa=\box45 91 | \@tempa=\box46 92 | \@tempa=\box47 93 | \@tempa=\box48 94 | \@tempa=\box49 95 | \c@columnbadness=\count94 96 | \c@finalcolumnbadness=\count95 97 | \last@try=\dimen110 98 | \multicolovershoot=\dimen111 99 | \multicolundershoot=\dimen112 100 | \mult@nat@firstbox=\box50 101 | \colbreak@box=\box51 102 | ) 103 | (/usr/share/texmf/tex/latex/amsmath/amsmath.sty 104 | Package: amsmath 2000/07/18 v2.13 AMS math features 105 | \@mathmargin=\skip45 106 | 107 | For additional information on amsmath, use the `?' option. 108 | (/usr/share/texmf/tex/latex/amsmath/amstext.sty 109 | Package: amstext 2000/06/29 v2.01 110 | 111 | (/usr/share/texmf/tex/latex/amsmath/amsgen.sty 112 | File: amsgen.sty 1999/11/30 v2.0 113 | \@emptytoks=\toks15 114 | \ex@=\dimen113 115 | )) 116 | (/usr/share/texmf/tex/latex/amsmath/amsbsy.sty 117 | Package: amsbsy 1999/11/29 v1.2d 118 | \pmbraise@=\dimen114 119 | ) 120 | (/usr/share/texmf/tex/latex/amsmath/amsopn.sty 121 | Package: amsopn 1999/12/14 v2.01 operator names 122 | ) 123 | \inf@bad=\count96 124 | LaTeX Info: Redefining \frac on input line 211. 125 | \uproot@=\count97 126 | \leftroot@=\count98 127 | LaTeX Info: Redefining \overline on input line 307. 128 | \classnum@=\count99 129 | \DOTSCASE@=\count100 130 | LaTeX Info: Redefining \ldots on input line 379. 131 | LaTeX Info: Redefining \dots on input line 382. 132 | LaTeX Info: Redefining \cdots on input line 467. 133 | \Mathstrutbox@=\box52 134 | \strutbox@=\box53 135 | \big@size=\dimen115 136 | LaTeX Font Info: Redeclaring font encoding OML on input line 567. 137 | LaTeX Font Info: Redeclaring font encoding OMS on input line 568. 138 | \macc@depth=\count101 139 | \c@MaxMatrixCols=\count102 140 | \dotsspace@=\muskip10 141 | \c@parentequation=\count103 142 | \dspbrk@lvl=\count104 143 | \tag@help=\toks16 144 | \row@=\count105 145 | \column@=\count106 146 | \maxfields@=\count107 147 | \andhelp@=\toks17 148 | \eqnshift@=\dimen116 149 | \alignsep@=\dimen117 150 | \tagshift@=\dimen118 151 | \tagwidth@=\dimen119 152 | \totwidth@=\dimen120 153 | \lineht@=\dimen121 154 | \@envbody=\toks18 155 | \multlinegap=\skip46 156 | \multlinetaggap=\skip47 157 | \mathdisplay@stack=\toks19 158 | LaTeX Info: Redefining \[ on input line 2666. 159 | LaTeX Info: Redefining \] on input line 2667. 160 | ) 161 | (/usr/share/texmf/tex/latex/booktabs/booktabs.sty 162 | Package: booktabs 2005/03/16 v1.6180 publication quality tables 163 | \heavyrulewidth=\dimen122 164 | \lightrulewidth=\dimen123 165 | \cmidrulewidth=\dimen124 166 | \belowrulesep=\dimen125 167 | \belowbottomsep=\dimen126 168 | \aboverulesep=\dimen127 169 | \abovetopsep=\dimen128 170 | \cmidrulesep=\dimen129 171 | \cmidrulekern=\dimen130 172 | \defaultaddspace=\dimen131 173 | \@cmidla=\count108 174 | \@cmidlb=\count109 175 | \@aboverulesep=\dimen132 176 | \@belowrulesep=\dimen133 177 | \@thisruleclass=\count110 178 | \@lastruleclass=\count111 179 | \@thisrulewidth=\dimen134 180 | ) 181 | (/usr/share/texmf/tex/latex/geometry/geometry.sty 182 | Package: geometry 2002/07/08 v3.2 Page Geometry 183 | \Gm@cnth=\count112 184 | \Gm@cntv=\count113 185 | \c@Gm@tempcnt=\count114 186 | \Gm@bindingoffset=\dimen135 187 | \Gm@wd@mp=\dimen136 188 | \Gm@odd@mp=\dimen137 189 | \Gm@even@mp=\dimen138 190 | \Gm@dimlist=\toks20 191 | ) 192 | No file Formulae.aux. 193 | \openout1 = `Formulae.aux'. 194 | 195 | LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 9. 196 | LaTeX Font Info: ... okay on input line 9. 197 | LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 9. 198 | LaTeX Font Info: ... okay on input line 9. 199 | LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 9. 200 | LaTeX Font Info: ... okay on input line 9. 201 | LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 9. 202 | LaTeX Font Info: ... okay on input line 9. 203 | LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 9. 204 | LaTeX Font Info: ... okay on input line 9. 205 | LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 9. 206 | LaTeX Font Info: ... okay on input line 9. 207 | -------------------- Geometry parameters 208 | paper: a4paper 209 | landscape: -- 210 | twocolumn: -- 211 | twoside: -- 212 | asymmetric: -- 213 | h-parts: 28.45274pt, 526.376pt, 42.67912pt 214 | v-parts: 42.67912pt, 768.2245pt, 34.14322pt 215 | hmarginratio: -- 216 | vmarginratio: -- 217 | lines: -- 218 | heightrounded: -- 219 | bindingoffset: 0.0pt 220 | truedimen: -- 221 | includehead: -- 222 | includefoot: -- 223 | includemp: -- 224 | driver: pdftex 225 | -------------------- Page layout dimensions and switches 226 | \paperwidth 597.50787pt 227 | \paperheight 845.04684pt 228 | \textwidth 526.376pt 229 | \textheight 768.2245pt 230 | \oddsidemargin -43.81725pt 231 | \evensidemargin -43.81725pt 232 | \topmargin -66.59087pt 233 | \headheight 12.0pt 234 | \headsep 25.0pt 235 | \footskip 30.0pt 236 | \marginparwidth 57.0pt 237 | \marginparsep 11.0pt 238 | \columnsep 10.0pt 239 | \skip\footins 9.0pt plus 4.0pt minus 2.0pt 240 | \hoffset 0.0pt 241 | \voffset 0.0pt 242 | \mag 1000 243 | 244 | (1in=72.27pt, 1cm=28.45pt) 245 | ----------------------- 246 | 247 | Overfull \hbox (35.47911pt too wide) in paragraph at lines 13--32 248 | [] 249 | [] 250 | 251 | 252 | Overfull \hbox (26.83899pt too wide) in paragraph at lines 35--48 253 | [] 254 | [] 255 | 256 | 257 | Package amsmath Warning: Foreign command \atop; 258 | (amsmath) \frac or \genfrac should be used instead 259 | (amsmath) on input line 56. 260 | 261 | 262 | Overfull \hbox (37.61845pt too wide) in paragraph at lines 51--63 263 | [] 264 | [] 265 | 266 | 267 | Overfull \hbox (8.12497pt too wide) in paragraph at lines 70--92 268 | [] 269 | [] 270 | 271 | [1 272 | 273 | {/usr/share/texmf/fonts/map/pdftex/updmap/pdftex.map}] 274 | Overfull \hbox (28.95041pt too wide) in paragraph at lines 96--105 275 | [] 276 | [] 277 | 278 | 279 | Overfull \hbox (24.67964pt too wide) in paragraph at lines 109--127 280 | [] 281 | [] 282 | 283 | 284 | File: chinese.png Graphic file (type png) 285 | 286 | Overfull \hbox (29.89485pt too wide) in paragraph at lines 143--144 287 | [][] 288 | [] 289 | 290 | [2 <./chinese.png (PNG copy)>] (./Formulae.aux) ) 291 | Here is how much of TeX's memory you used: 292 | 1633 strings out of 256216 293 | 19925 string characters out of 1917065 294 | 94793 words of memory out of 1500000 295 | 4949 multiletter control sequences out of 10000+200000 296 | 5353 words of font info for 20 fonts, out of 1200000 for 2000 297 | 645 hyphenation exceptions out of 8191 298 | 27i,11n,20p,493b,187s stack positions out of 5000i,500n,6000p,200000b,15000s 299 | 309 | Output written on Formulae.pdf (2 pages, 167248 bytes). 310 | PDF statistics: 311 | 62 PDF objects out of 1000 (max. 8388607) 312 | 0 named destinations out of 1000 (max. 131072) 313 | 6 words of extra memory for PDF output out of 10000 (max. 10000000) 314 | 315 | -------------------------------------------------------------------------------- /formulae/Formulae.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper]{article} 2 | 3 | \usepackage{graphicx} 4 | \usepackage{multicol} 5 | \usepackage{amsmath} 6 | \usepackage{booktabs} 7 | \usepackage[left=1cm, right=1.5cm, top=1.5cm, bottom=1.2cm]{geometry} 8 | 9 | \begin{document} 10 | 11 | \section{Combinatorics} 12 | \begin{center} 13 | \begin{tabular}{@{}ll|ll@{}} 14 | \toprule 15 | \multicolumn{4}{c}{Classical Problems} \\ \midrule 16 | HanoiTower(HT) min steps & $T_n = 2^n - 1$ & Regions by $n$ lines & $L_n = n(n+1)/2+1$ \\ 17 | Regions by $n$ Zig lines & $Z_n=2n^2-n+1$ & Joseph Problem (every $m$-th) & $F_1=0$, $F_i=(F_{i-1}+m)\% i $\\ 18 | Joseph Problem (every $2$nd) & rotate $n$ $1$-bit to left & HanoiTower (no direct $A$ to $C$) & $T_n = 3^n - 1$ \\ 19 | Bounded regions by $n$ lines & $(n^2-3n+2)/2$ & Joseph given pos $j$,find $m$.($\downarrow$con.) & $m\equiv 1$ (mod $\frac{L}{p})$,\\ 20 | HT min steps A to C clockw.& $Q_n=2R_{n-1}+1$ & $L(n)=lcm(1,...,n)$, $p$ prime $\in [\frac{n}{2},n]$ & $m\equiv j+1-n$ (mod $p$)\\ 21 | HT min steps C to A clockw.& $R_n=2R_{n-1}+Q_{n-1}+2$ & $\sum_{i=1}^n i^2 = n(n+1)(2n+1)/6$ & $\sum_{i=1}^n i^3 = n^2(n+1)^2/4$\\ 22 | Egyptian Fraction & $\frac{m}{n}=\frac{1}{\lceil n/m \rceil}+(\frac{m}{n}-\frac{1}{\lceil n/m \rceil})$ & Farey Seq given $m/n$, $m'/n'$ & $m''=\lfloor (n+N)/n' \rfloor m'-m$\\ 23 | Farey Seq given $m/n$, $m''/n''$ & $m'/n'=\frac{m+m''}{n+n''}$ & $m/n=0/1$, $m'/n'=1/N$ & $n''=\lfloor (n+N)/n' \rfloor n'-n$\\ 24 | \#labeled rooted trees & $n^{n-1}$ & \#labeled unrooted trees & $n^{n-2}$ \\ 25 | \#SpanningTree of $G$ (no SL) & $C(G)=D(G)-A(G)(\downarrow)$ & Stirling's Formula & $n! \sim \sqrt{2 \pi n} \left(\frac{n}{e}\right)^n(1+\frac{1}{12n})$ \\ 26 | $D:$ DegMat; $A:$ AdjMat & $Ans=|\det(C-1r-1c)|$ & Farey Seq & $m n' - m' n = -1$ \\ 27 | & &\#ways $0\rightarrow m$ in $n$ steps (never $<0$) & $\frac{m+1}{\tfrac{n+m}2+1}\binom{n}{\tfrac{n+m}2}$ \\ 28 | \multicolumn{3}{l}{$\#seq\langle a_0,...,a_{mn} \rangle$ of $1$'s and $(1-m)$'s with sum $+1 = \binom{mn+1}{n}\frac{1}{mn+1}=\binom{mn}{n}\frac{1}{(m-1)n+1}$ } \\ 29 | 30 | \bottomrule 31 | \end{tabular} 32 | \end{center} 33 | 34 | \begin{center} 35 | \begin{tabular}{@{}l|l|l@{}} 36 | \toprule 37 | \multicolumn{3}{c}{Binomial Coefficients} \\ \midrule 38 | $\binom{n}{k}=\frac{n!}{k!(n-k)!}$, int $n \ge k \ge 0$ & $\binom{n}{k}=\binom{n}{n-k}$, int $n\ge 0$, int $k$ & $\binom{r}{k}=\frac{r}{k}\binom{r-1}{k-1}$, int $k\ne 0$ \\ 39 | $\binom{r}{k}=(-1)^k \binom{k-r-1}{k}$, int $k$ & $\binom{r}{m}\binom{m}{k}=\binom{r}{k}\binom{r-k}{m-k}$, int $m,k$ & $(x+y)^r = \sum_{k} \binom{r}{k}x^ky^{r-k}$, int $r \ge 0$ or $|x/y|<1$ \\ 40 | $\binom{r}{k}=\binom{r-1}{k}+\binom{r-1}{k-1}$, int $k$ & $\sum_{k\le n}\binom{r+k}{k}=\binom{r+n+1}{n}$, int $n$ & $\sum_{k=0}^n\binom{k}{m}=\binom{n+1}{m+1}$, int $m,n\ge 0$ \\ 41 | $\binom{r+s}{n}=\sum_{k}\binom{r}{k}\binom{s}{n-k}$, int $n$ & $\sum_{k\le m}\binom{r}{k}(\frac{r}{2}-k)=\frac{m+1}{2}\binom{r}{m+1}$, int $m$ & $\sum_{k\le m}\binom{r}{k}(-1)^k = (-1)^m\binom{r-1}{m}$, int $m$ \\ 42 | $\sum_{k}\binom{r}{m+k}\binom{s}{n-k}=\binom{r+s}{m+n}$, int $m,n$ & $\binom{\binom{k}{2}}{2}=3\binom{k+1}{4}$ \quad \vline \quad $\sum_{i=0}^n\binom{n}{i}^2=\binom{2n}{n}$ & $\sum_{k}\binom{l}{m+k}\binom{s}{n+k}=\binom{l+s}{l-m+n}$ int $l\ge0$, int $m,n$\\ 43 | $\sum_k\binom{n}{2k}=2^{n-even(n)}$ & $lcm_{i=0}^n\binom{n}{i}=\frac{L(n+1)}{n+1}$ & $S(n,1)=S(n,n)=n \Rightarrow S(n,k)=\binom{n+1}{k}-\binom{n-1}{k-1}$\\ 44 | $\sum_{i=1}^n\binom{n}{i}F_i=F_{2n}$, $F_n=$ $n$-th Fib & $\sum_i\binom{n-i}{i}=F_{n+1}$ & \\ 45 | 46 | \bottomrule 47 | \end{tabular} 48 | \end{center} 49 | 50 | \begin{center} 51 | \begin{tabular}{@{}l|l|l@{}} 52 | \toprule 53 | \multicolumn{3}{c}{Famous Numbers} \\ \midrule 54 | 55 | Catalan & $C_0=1$, $C_n=\frac{1}{n+1}\binom{2n}{n} = \sum_{i=0}^{n-1}C_iC_{n-i-1} = \frac{4n-2}{n+1}C_{n-1}$ & \\ 56 | Stirling 1st kind & $\left[{0\atop 0}\right]=1$, $\left[{n\atop 0}\right]=\left[{0\atop n}\right]=0$, $\left[{n\atop k}\right]=(n-1)\left[{n-1\atop k}\right]+\left[{n-1\atop k-1}\right]$ & \#perms of $n$ objs with exactly $k$ cycles\\ 57 | Stirling 2nd kind & $\left\{{n\atop 1}\right\}=\left\{{n\atop n}\right\}=1$, $\left\{{n\atop k}\right\} = k \left\{{ n-1 \atop k }\right\} + \left\{{n-1\atop k-1}\right\}$ & \#ways to partition $n$ objs into $k$ nonempty sets\\ 58 | Euler & $\left \langle {n\atop 0} \right \rangle = \left \langle {n\atop n-1} \right \rangle = 1 $, $\left \langle {n\atop k} \right \rangle = (k+1) \left \langle {n-1\atop {k}} \right \rangle + (n-k)\left \langle {{n-1}\atop {k-1}} \right \rangle$ & \#perms of $n$ objs with exactly $k$ ascents \\ 59 | Euler 2nd Order & $\left \langle \!\!\left \langle {n\atop k} \right \rangle \!\! \right \rangle = (k+1) \left \langle \!\! \left \langle {{n-1}\atop {k}} \right \rangle \!\! \right \rangle +(2n-k-1)\left \langle \!\! \left \langle {{n-1}\atop {k-1}} \right \rangle \!\! \right \rangle$ & \#perms of ${1,1,2,2,...,n,n}$ with exactly $k$ ascents \\ 60 | 61 | \bottomrule 62 | \end{tabular} 63 | \end{center} 64 | 65 | 66 | {\bf Burnside's Lemma:} $L=\frac{1}{|G|}\sum_{k=1}^n|Z_k|=\frac{1}{|G|}\sum_{a_i \in G}C_1(a_i)$. $Z_k:$ the set of permutations in $G$ under which $k$ stays stable; $C_1(a_i):$ the number of cycles of order $1$ in $a_i$. \quad {\bf P\'olya's Theorem:} The number of colorings of $n$ objects with $m$ colors $L=\frac{1}{|\overline{G}|}\sum_{g_i \in \overline{G}}{m^{c(g_i)}}$. $\overline{G}:$ the group over $n$ objects; $c(g_i):$the number of cycles in $g_i$. 67 | 68 | % Regular Polyhedron Coloring 69 | \begin{center} 70 | \begin{tabular}{@{}ll|lr@{}} 71 | \toprule 72 | \multicolumn{4}{c}{Regular Polyhedron Coloring {\bf with at most $n$ colors (up to isomorph)} } \\ \hline 73 | \it Description & \it Formula & Remarks & \\ \hline 74 | {\bf vertices of octahedron} or {\bf faces of cube} & $ (n^6 + 3 n^4 + 12 n^3 + 8 n^2)/24$ & & $(V,F,E)$\\ 75 | 76 | {\bf vertices of cube} or {\bf faces of octahedron} & $ (n^8 + 17 n^4 + 6 n^2)/24$ & tetrahedron: & $(4,4,6)$ \\ 77 | 78 | {\bf edges of cube} or {\bf edges of octahedron} & $ (n^{12} + 6 n^7 + 3 n^6 + 8 n^4 + 6 n^3)/24$ & cube: & $(8,6,12)$ \\ 79 | 80 | {\bf vertices} or {\bf faces of tetrahedron} & $(n^4 + 11 n^2)/12$ & octahedron:& $(6,8,12)$ \\ 81 | 82 | {\bf edges of tetrahedron} & $(n^6 + 3 n^4 + 8 n^2)/12$ & dodecahedron: & $(20,12,30)$ \\ 83 | 84 | {\bf vertices of icosahedron} or {\bf faces of dodecahedron} & $(n^{12} + 15 n^6 + 44 n^4)/60$ & icosahedron & $(12,20,30)$\\ 85 | 86 | {\bf vertices of dodecahedron} or {\bf faces of icosahedron} & $(n^{20} + 15 n^{10} + 20 n^8 + 24 n^4)/60$ &\\ 87 | 88 | {\bf edges of dodecahedron} or {\bf edges of icosahedron} & $(n^{30} + 15 n^{16} + 20 n^{10} + 24 n^6)/60$ & \multicolumn{2}{c}{\emph{This row may be wrong.}}\\ 89 | 90 | \bottomrule 91 | \end{tabular} 92 | \end{center} 93 | \newpage 94 | \section{Number Theory} 95 | \begin{center} 96 | \begin{tabular}{@{}l|l|l@{}} 97 | \toprule 98 | \multicolumn{3}{c}{Classical Theorems} \\ \midrule 99 | exp of $p$ in $n!$ is $\sum_{i\ge 1}[\frac{n}{p^i}]$ & $p_n \sim n\log n$; \quad $\forall_{n>1} \exists_{n\frac{p}{2} \Rightarrow \left(\frac{a}{p}\right)=(-1)^s$\\ 123 | $ \left(\frac{p}{q}\right)\left(\frac{q}{p}\right)=(-1)^{\frac{p-1}{2}\frac{q-1}{2}} $ & \multicolumn{2}{l}{Gauss Integer $\pi=a+bi$. Norm$(\pi)=p$ prime $\Rightarrow$ $\pi$ and $\overline\pi$ prime, $p$ not prime}\\ 124 | 125 | \bottomrule 126 | \end{tabular} 127 | \end{center} 128 | 129 | 130 | \section{Probability} 131 | \begin{center} 132 | \begin{tabular}{@{}ll|ll@{}} 133 | \toprule 134 | \multicolumn{4}{c}{Classical Formulae} \\ \midrule 135 | Ballot.Always $\#A > k\#B$ & $Pr=\frac{a-kb}{a+b}\binom{a+b}{a}$ & Ballot.Always $\#B-\#A\le k$ & $Pr=1-\frac{n!m!}{(n+k+1)!(m-k-1)!}$ \\ 136 | $E(X+Y)=EX+EY$ & $E(\alpha X)=\alpha EX$ & if X,Y indep. $\Leftrightarrow E(XY)=(EX)(EY)$ 137 | \\ 138 | 139 | \bottomrule 140 | \end{tabular} 141 | \end{center} 142 | 143 | \includegraphics{chinese.png} 144 | 145 | 146 | 147 | 148 | \end{document} -------------------------------------------------------------------------------- /formulae.tex: -------------------------------------------------------------------------------- 1 | \section{Formelsammlung} 2 | \subsection{Combinatorics} 3 | \begin{center} 4 | \begin{tabular}{@{}ll|ll@{}} 5 | \toprule 6 | \multicolumn{4}{c}{Classical Problems} \\ \midrule 7 | HanoiTower(HT) min steps & $T_n = 2^n - 1$ & Regions by $n$ lines & $L_n = n(n+1)/2+1$ \\ 8 | Regions by $n$ Zig lines & $Z_n=2n^2-n+1$ & Joseph Problem (every $m$-th) & $F_1=0$, $F_i=(F_{i-1}+m)\% i $\\ 9 | Joseph Problem (every $2$nd) & rotate $n$ $1$-bit to left & HanoiTower (no direct $A$ to $C$) & $T_n = 3^n - 1$ \\ 10 | Bounded regions by $n$ lines & $(n^2-3n+2)/2$ & Joseph given pos $j$,find $m$.($\downarrow$con.) & $m\equiv 1$ (mod $\frac{L}{p})$,\\ 11 | HT min steps A to C clockw.& $Q_n=2R_{n-1}+1$ & $L(n)=lcm(1,...,n)$, $p$ prime $\in [\frac{n}{2},n]$ & $m\equiv j+1-n$ (mod $p$)\\ 12 | HT min steps C to A clockw.& $R_n=2R_{n-1}+Q_{n-1}+2$ & $\sum_{i=1}^n i^2 = n(n+1)(2n+1)/6$ & $\sum_{i=1}^n i^3 = n^2(n+1)^2/4$\\ 13 | Egyptian Fraction & $\frac{m}{n}=\frac{1}{\lceil n/m \rceil}+(\frac{m}{n}-\frac{1}{\lceil n/m \rceil})$ & Farey Seq given $m/n$, $m'/n'$ & $m''=\lfloor (n+N)/n' \rfloor m'-m$\\ 14 | Farey Seq given $m/n$, $m''/n''$ & $m'/n'=\frac{m+m''}{n+n''}$ & $m/n=0/1$, $m'/n'=1/N$ & $n''=\lfloor (n+N)/n' \rfloor n'-n$\\ 15 | \#labeled rooted trees & $n^{n-1}$ & \#labeled unrooted trees & $n^{n-2}$ \\ 16 | \#SpanningTree of $G$ (no SL) & $C(G)=D(G)-A(G)(\downarrow)$ & Stirling's Formula & $n! \sim \sqrt{2 \pi n} \left(\frac{n}{e}\right)^n(1+\frac{1}{12n})$ \\ 17 | $D:$ DegMat; $A:$ AdjMat & $Ans=|\det(C-1r-1c)|$ & Farey Seq & $m n' - m' n = -1$ \\ 18 | \#heaps of a tree (keys: $1..n$) & $\frac{(n-1)!}{\prod_{i\neq root} \mathrm{size}(i)}$ &\#ways $0\rightarrow m$ in $n$ steps (never $<0$) & $\frac{m+1}{\tfrac{n+m}2+1}\binom{n}{\tfrac{n+m}2}$ \\ 19 | \multicolumn{3}{l}{$\#seq\langle a_0,...,a_{mn} \rangle$ of $1$'s and $(1-m)$'s with sum $+1 = \binom{mn+1}{n}\frac{1}{mn+1}=\binom{mn}{n}\frac{1}{(m-1)n+1}$ } \vline & $\mathrm{D}_n=n\mathrm{D}_{n-1}+(-1)^n$ \\ 20 | 21 | \bottomrule 22 | \end{tabular} 23 | \end{center} 24 | 25 | \begin{center} 26 | \begin{tabular}{@{}l|l|l@{}} 27 | \toprule 28 | \multicolumn{3}{c}{Binomial Coefficients} \\ \midrule 29 | $\binom{n}{k}=\frac{n!}{k!(n-k)!}$, int $n \ge k \ge 0$ & $\binom{n}{k}=\binom{n}{n-k}$, int $n\ge 0$, int $k$ & $\binom{r}{k}=\frac{r}{k}\binom{r-1}{k-1}$, int $k\ne 0$ \\ 30 | $\binom{r}{k}=(-1)^k \binom{k-r-1}{k}$, int $k$ & $\binom{r}{m}\binom{m}{k}=\binom{r}{k}\binom{r-k}{m-k}$, int $m,k$ & $(x+y)^r = \sum_{k} \binom{r}{k}x^ky^{r-k}$, int $r \ge 0$ or $|x/y|<1$ \\ 31 | $\binom{r}{k}=\binom{r-1}{k}+\binom{r-1}{k-1}$, int $k$ & $\sum_{k\le n}\binom{r+k}{k}=\binom{r+n+1}{n}$, int $n$ & $\sum_{k=0}^n\binom{k}{m}=\binom{n+1}{m+1}$, int $m,n\ge 0$ \\ 32 | $\binom{r+s}{n}=\sum_{k}\binom{r}{k}\binom{s}{n-k}$, int $n$ & $\sum_{k\le m}\binom{r}{k}(\frac{r}{2}-k)=\frac{m+1}{2}\binom{r}{m+1}$, int $m$ & $\sum_{k\le m}\binom{r}{k}(-1)^k = (-1)^m\binom{r-1}{m}$, int $m$ \\ 33 | $\sum_{k}\binom{r}{m+k}\binom{s}{n-k}=\binom{r+s}{m+n}$, int $m,n$ & $\binom{\binom{k}{2}}{2}=3\binom{k+1}{4}$ \quad \vline \quad $\sum_{i=0}^n\binom{n}{i}^2=\binom{2n}{n}$ & $\sum_{k}\binom{l}{m+k}\binom{s}{n+k}=\binom{l+s}{l-m+n}$ int $l\ge0$, int $m,n$\\ 34 | $\sum_k\binom{n}{2k}=2^{n-even(n)}$ & $lcm_{i=0}^n\binom{n}{i}=\frac{L(n+1)}{n+1}$ & $S(n,1)=S(n,n)=n \Rightarrow S(n,k)=\binom{n+1}{k}-\binom{n-1}{k-1}$\\ 35 | $\sum_{i=1}^n\binom{n}{i}F_i=F_{2n}$, $F_n=$ $n$-th Fib & $\sum_i\binom{n-i}{i}=F_{n+1}$ & \\ 36 | 37 | \bottomrule 38 | \end{tabular} 39 | \end{center} 40 | 41 | \begin{center} 42 | \begin{tabular}{@{}l|l|l@{}} 43 | \toprule 44 | \multicolumn{3}{c}{Famous Numbers} \\ \midrule 45 | 46 | Catalan & $C_0=1$, $C_n=\frac{1}{n+1}\binom{2n}{n} = \sum_{i=0}^{n-1}C_iC_{n-i-1} = \frac{4n-2}{n+1}C_{n-1}$ & \\ 47 | Stirling 1st kind & $\left[{0\atop 0}\right]=1$, $\left[{n\atop 0}\right]=\left[{0\atop n}\right]=0$, $\left[{n\atop k}\right]=(n-1)\left[{n-1\atop k}\right]+\left[{n-1\atop k-1}\right]$ & \#perms of $n$ objs with exactly $k$ cycles\\ 48 | Stirling 2nd kind & $\left\{{n\atop 1}\right\}=\left\{{n\atop n}\right\}=1$, $\left\{{n\atop k}\right\} = k \left\{{ n-1 \atop k }\right\} + \left\{{n-1\atop k-1}\right\}$ & \#ways to partition $n$ objs into $k$ nonempty sets\\ 49 | Euler & $\left \langle {n\atop 0} \right \rangle = \left \langle {n\atop n-1} \right \rangle = 1 $, $\left \langle {n\atop k} \right \rangle = (k+1) \left \langle {n-1\atop {k}} \right \rangle + (n-k)\left \langle {{n-1}\atop {k-1}} \right \rangle$ & \#perms of $n$ objs with exactly $k$ ascents \\ 50 | Euler 2nd Order & $\left \langle \!\!\left \langle {n\atop k} \right \rangle \!\! \right \rangle = (k+1) \left \langle \!\! \left \langle {{n-1}\atop {k}} \right \rangle \!\! \right \rangle +(2n-k-1)\left \langle \!\! \left \langle {{n-1}\atop {k-1}} \right \rangle \!\! \right \rangle$ & \#perms of ${1,1,2,2,...,n,n}$ with exactly $k$ ascents \\ 51 | Bell & $B_1 = 1$, $B_n = \sum_{k=0}^{n-1} B_k \binom{n-1}{k} = \sum_{k=0}^n\left\{{n\atop k}\right\}$ & \#partitions of $1..n$ (Stirling 2nd, no limit on k)\\ 52 | 53 | \bottomrule 54 | \end{tabular} 55 | \end{center} 56 | 57 | \begin{tabular}{@{}c|c|c|c|c|l@{}} 58 | \toprule 59 | \multicolumn{6}{c}{The Twelvefold Way (Putting $n$ balls into $k$ boxes)} \\ \hline 60 | Balls & same & distinct & same & distinct & \\ 61 | Boxes & same & same & distinct & distinct & Remarks\\ 62 | \hline 63 | - & $\mathrm{p}_k(n)$ & $\sum_{i=0}^k \left\{{n\atop i}\right\}$ & $\binom{n+k-1}{k-1}$ & $k^n$ & $\mathrm{p}_k(n)$: \#partitions of $n$ into $\le k$ positive parts \\ 64 | $\mathrm{size}\ge 1$ & $\mathrm{p}(n,k)$ & $\left\{{n\atop k}\right\}$ & $\binom{n-1}{k-1}$ & $k!\left\{{n\atop k}\right\}$ & $\mathrm{p}(n,k)$: \#partitions of $n$ into $k$ positive parts (\lstinline|NrPartitions|)\\ 65 | $\mathrm{size}\le 1$ & $[n \le k]$ & $[n \le k]$ & $\binom{k}{n}$ & $n!\binom{k}{n}$ & $[cond]$: $1$ if $cond=true$, else $0$\\ 66 | 67 | 68 | \bottomrule 69 | \end{tabular} 70 | 71 | %\subsection{Probability} 72 | \begin{center} 73 | \begin{tabular}{@{}ll|ll@{}} 74 | \toprule 75 | \multicolumn{4}{c}{Classical Formulae} \\ \midrule 76 | Ballot.Always $\#A > k\#B$ & $Pr=\frac{a-kb}{a+b}$ & Ballot.Always $\#B-\#A\le k$ & $Pr=1-\frac{a!b!}{(a+k+1)!(b-k-1)!}$ \\ 77 | Ballot.Always $\#A \ge k\#B$ & $Pr=\frac{a+1-kb}{a+1}$ & Ballot.Always $\#A\ge \#B+k$ & $Num=\frac{a-k+1-b}{a-k+1}\binom{a+b-k}{b}$\\ 78 | $E(X+Y)=EX+EY$ & $E(\alpha X)=\alpha EX$ & $X$,$Y$ indep. $\Leftrightarrow E(XY)=(EX)(EY)$ 79 | \\ 80 | 81 | \bottomrule 82 | \end{tabular} 83 | \end{center} 84 | 85 | {\bf Burnside's Lemma:} $L=\frac{1}{|G|}\sum_{k=1}^n|Z_k|=\frac{1}{|G|}\sum_{a_i \in G}C_1(a_i)$. $Z_k:$ the set of permutations in $G$ under which $k$ stays stable; $C_1(a_i):$ the number of cycles of order $1$ in $a_i$. \quad {\bf P\'olya's Theorem:} The number of colorings of $n$ objects with $m$ colors $L=\frac{1}{|\overline{G}|}\sum_{g_i \in \overline{G}}{m^{c(g_i)}}$. $\overline{G}:$ the group over $n$ objects; $c(g_i):$the number of cycles in $g_i$. 86 | 87 | \begin{center} 88 | % Regular Polyhedron Coloring 89 | %\begin{center} 90 | \begin{tabular}{@{}ll|lr@{}} 91 | \toprule 92 | \multicolumn{4}{c}{Regular Polyhedron Coloring {\bf with at most $n$ colors (up to isomorph)} } \\ \hline 93 | \it Description & \it Formula & Remarks & \\ \hline 94 | {\bf vertices of octahedron} or {\bf faces of cube} & $ (n^6 + 3 n^4 + 12 n^3 + 8 n^2)/24$ & & $(V,F,E)$\\ 95 | 96 | {\bf vertices of cube} or {\bf faces of octahedron} & $ (n^8 + 17 n^4 + 6 n^2)/24$ & tetrahedron: & $(4,4,6)$ \\ 97 | 98 | {\bf edges of cube} or {\bf edges of octahedron} & $ (n^{12} + 6 n^7 + 3 n^6 + 8 n^4 + 6 n^3)/24$ & cube: & $(8,6,12)$ \\ 99 | 100 | {\bf vertices} or {\bf faces of tetrahedron} & $(n^4 + 11 n^2)/12$ & octahedron:& $(6,8,12)$ \\ 101 | 102 | {\bf edges of tetrahedron} & $(n^6 + 3 n^4 + 8 n^2)/12$ & dodecahedron: & $(20,12,30)$ \\ 103 | 104 | {\bf vertices of icosahedron} or {\bf faces of dodecahedron} & $(n^{12} + 15 n^6 + 44 n^4)/60$ & icosahedron & $(12,20,30)$\\ 105 | 106 | {\bf vertices of dodecahedron} or {\bf faces of icosahedron} & $(n^{20} + 15 n^{10} + 20 n^8 + 24 n^4)/60$ &\\ 107 | 108 | {\bf edges of dodecahedron} or {\bf edges of icosahedron} & $(n^{30} + 15 n^{16} + 20 n^{10} + 24 n^6)/60$ & \multicolumn{2}{c}{\emph{This row may be wrong.}}\\ 109 | 110 | \bottomrule 111 | \end{tabular} 112 | \end{center} 113 | 114 | \textbf{Exponential families (unlabelled)}: $h(n) =$ number of possible hands of weight $n$, 115 | $h(n,k) =$ number of hands of weight $n$ with $k$ cards, $d(n) =$ number of cards of weight n. 116 | Then $k \cdot h(n, k) = \sum_{r, m \ge 1} h(n - rm, k - m)\cdot d(r)$ and 117 | $n \cdot h(n) = \sum_{m \ge 1} h(n - m) \cdot \sum_{r | m} r\cdot d(r)$. 118 | %\newpage 119 | 120 | \subsection{Number Theory} 121 | \begin{center} 122 | \begin{tabular}{@{}l|l|l@{}} 123 | \toprule 124 | \multicolumn{3}{c}{Classical Theorems} \\ \midrule 125 | exp of $p$ in $n!$ is $\sum_{i\ge 1}[\frac{n}{p^i}]$ & $p_n \sim n\log n$; \quad $\forall_{n>1} \exists_{n\frac{p}{2} \Rightarrow \left(\frac{a}{p}\right)=(-1)^s$\\ 150 | $ \left(\frac{p}{q}\right)\left(\frac{q}{p}\right)=(-1)^{\frac{p-1}{2}\frac{q-1}{2}} $ & \multicolumn{2}{l}{Gauss Integer $\pi=a+bi$. Norm$(\pi)=p$ prime $\Rightarrow$ $\pi$ and $\overline\pi$ prime, $p$ not prime}\\ 151 | 152 | \bottomrule 153 | \end{tabular} 154 | \end{center} 155 | 156 | \subsection{Game Theory} 157 | \LTXtable{\textwidth}{Formulae_gametheory.tex} 158 | 159 | \begin{itemize} 160 | \item Johnson's Reweighting Algorithm: add a new source S, it can reach all other nodes with 0 cost. Use bellmanford to calculate the shortest path d[i] from S to all other nodes i. Exit when negative cycle is found. Otherwise the weights of all edges (u,v) in the original graph are changed to d[u]+w[u,v]-d[v]. Now all weights are nonnegative, so dijkstra algorithm can be used. 161 | \item feasible flow in a network with both upper and lower capacity constraints, no source or sink : capacity are changed to upperbound-lowerbound. Add a new source and a sink. let M[v] = (sum of lowerbounds of ingoing edges to v) - (sum of lowserbounds of outgoing edges from v). For all v, if M[v]>0 then add edge (S,v) with capacity M, otherwise add (v,T) with capacity -M. If all outgoing edges from S are full, then a feasible flow exists, it is the flow plus the original lowerbounds. 162 | \item feasible flow in a network with both upper and lower capacity constraints, with source s and sink t: add edge (t,s) with capacity infinity. Binary search for the lower bound, check whether a feasible exists for a network WITHOUT source or sink (B). 163 | \item system of difference constraints: change all the conditions to the form a-b<=c. For every such condition add an edge (b,a) with weight c. Add a source which can reach all the nodes with 0 cost. Find shortest paths with bellman ford from s. d[v] is a solution. 164 | \item min-weight vertex cover in a bipartite graph: partition into A and B. add edges $s \rightarrow A$ with capacities $w(A)$ and edges $B \rightarrow t$ with capacities $w(B)$. add edges of capacity $\infty$ from A to B where there are edges in the graph. answer is maxflow. the vertex cover is the set of nodes that are 165 | adjacent to cut edges, or alternatively, the left-side nodes NOT reachable from the source and the right-side edges reachable from the source (in the residual network). 166 | \item general graph: complement of a vertex cover is an independent set $\rightarrow$ max-weight independent set is complement of min-weight vertex cover. 167 | \item optimal proportion spanning tree: z=sigma(benifit[i] * x[i]) - I * sigma(cost[i] * x[i]) = sigma(d[i] * x[i]). binary search for I, find the MST so that z = 0, then I is the best proportion. 168 | \item optimal proportion cycle: same as above, change the "find MST" to "check if there're positive cycles" 169 | \item Bipartite Graph: Min Cover (fewest nodes cover all edges) = max matching. Min path covering for DAG: n - maxmatching. Min dominating set = max matching + isolated nodes. Max independent set = n - max matching 170 | \item Bipartite matching with weights on the left-hand nodes, minimizing the matched weight sum: 171 | sort left-hand nodes ascending by weight, then just use the normal bipartite matching algorithm (Kuhn's) 172 | \item Closure problem: Find a subset $V' \subset V$ such that $V'$ is closed (every successor of a node in $V'$ is also in $V'$) and such that $\sum_{v \in V'} w(v)$ is maximal under all such subsets $V'$. We use min-cut: for every node $v$, if $w(v) > 0$, add an edge $(S, v)$ with capacity $w(v)$, otherwise add edge $(v,T)$ with capacity $-w(v)$. Add edges $(v,w)$ with capacity $\infty$ for all edges $(v,w)$ in the original graph. The source partition of the min-cut is the optimal $V'$. 173 | \item Poset width / partition into maximum number of chains: Duplicate each element 174 | in $\{0,\ldots,n-1\}$, add edge $(u, n+v)$ for $u < v$. Edges in maximum matching in the 175 | resulting bipartite graph correspond to chain edges. Width is n - max matching. 176 | For weighted nodes, duplicate elements so they form an antichain. 177 | \item Erdős–Gallai theorem: A sequence of non-negative integers $d_1\geq\cdots\geq d_n$ can be represented as the degree sequence of a finite simple graph on $n$ vertices if and only if $d_1+\cdots+d_n$ is even and $\sum^{k}_{i=1}d_i\leq k(k-1)+ \sum^n_{i=k+1} \min(d_i,k) \ \forall\ 1 \leq k \leq n$ 178 | \item In a connected undirected graph, a random walk (uniform choice of next node) with any start node will hit all nodes in expected time $2m\cdot (n-1)$. We can also walk on the projection of some more complex graph into fewer dimensions. E.g. 2-SAT: Let $T$ be a valid truth assignment. Start with any assignment $T*$. Let $n$ be the number of variables in which $T$ and $T*$ coincide. If we fix a broken clause by picking any of its variables at random and adding it to $T*$, we increase $n$ with probability of at least $\frac{1}{2}$ (and decrease it otherwise). The graph we walk on is the integer number line, and we are expected to hit $T$ after $2n^2$ iterations. If the distribution is non-uniform against your favor, it does not work at all (even if the probability to go in the "right" direction is only slightly less than $\frac{1}{2}$) 179 | \item Fixed-parameter Steiner tree with terminal set $T$ on a graph $V$: Let $f(X \subseteq T, v)$ be the size of the 180 | smallest subtree connecting the vertices $X \cup \{v\}$. Then: 181 | 182 | \begin{align*} 183 | \forall v \in V: &&f(\{\}, v) &= 0 && \\ 184 | \forall x \in T, v \in V: &&f(\{x\}, v) &= d(x, v) && \\ 185 | \forall X \subseteq T, |X| \geq 2, v \in X: &&f(X, v) &= \min_{w\in V} d(v, w) + f(X \setminus \{v\}, w) && \\ 186 | \forall X \subseteq T, |X| \geq 2, v \in V \setminus X: 187 | &&f(X, v) &= \min_{\substack{w\in V \\ X' \subset X \\ X' \neq X }} 188 | d(v, w) + f(X', w) + f(X \setminus X', w) 189 | \end{align*} 190 | 191 | Runtime: $\mathcal{O}(|V| \cdot 3^{|T|})$ 192 | 193 | \item Generally useful solution ideas (always consider!): divide and conquer, binary search, precomputation, output-sensitive algorithms, meet-in-the-middle, use different algos for different situations, hashing 194 | 195 | \end{itemize} 196 | --------------------------------------------------------------------------------