Professional Documents
Culture Documents
IIUM cat-us-trophy
Contents
Combinatorics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Data structures (BIT, BIT2D, RMQ-DP, RMQ-segment tree, union-find, misofs tree, treap)
Number theory (*gcd, totient, sieve, modexp, rabinmiller) . . . . . . . . . . . . . . . . . . . .
String algorithms (SuffixA, Aho-Corasick, KMP) . . . . . . . . . . . . . . . . . . . . . . . . .
Graph algorithms (LCA, SCC, BPM-konig, Bellman-Ford, NetFlow, MinCost MaxFlow) . . .
Games theory (Grundy, Misre) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Geometry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Appendices (LU, Blossom, binary search, ASCII table) . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.vimrc
template.cpp
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<map>
#include<cassert>
#include<climits>
using namespace std;
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
sz
pb
VI
VS
size()
push_back
vector<int>
vector<string>
2
4
7
10
13
19
19
22
Combinatorics
Mathematical Sums
=0 2= ( + 1)/2
= ( + 1)(2 + 1)/6
=0
+1
1)/( 1)
=0 = (
= ( + )( + 1)/2
=
3 = 2 ( + 1)2 /4
=0
5 = (26 + 65 + 54 2 )/12
=0
+1
+ +2 )/( 1)2
=0 = ( ( + 1)
Binomial coefficients
0
1
2
3
4
5
6
7
8
9
10
11
12
0
1
1
1
1
1
1
1
1
1
1
1
1
1
0
1
2 1
3 3
1
4 6
4
1
5 10 10
5
6 15 20 15
7 21 35 35
8 28 56 70
9 36 84 126
10 45 120 210
11 55 165 330
12 66 220 495
1 2
3
4
1
6
21
56
126
252
462
792
5
1
7
28
84
210
462
924
6
1
8
36
120
330
792
7
10
11
12
()
= !
( ) (()!!
) (1)
1
=
+ ) 1
(
( )
1
( )
( ) =
+1
=
(+1)
()
+1
=
+1
( ) ()
= +1
+1
()
1
1
=1 2 ()= 2
2 2
=1 = ( + )2
9
1
45 10 1
(+) ()( )
165 55 11 1
=
495 220 66 12 1
() =0
+
= =1
8
9 10 11 12
(+1)
Number of ways to pick a multiset of size from elements:
(+1)
(+)
Number of -tuples of non-negative integers with sum :
, at most :
( 1 ) 1
Number of -tuples of positive integers with sum :
1
(+)
Number of lattice paths from (0, 0) to (, ), restricted to east and north steps:
(2)
1
1
Catalan numbers = +1 . 0 = 1, = =0 1 . +1 = 4+2
.
+2
0 , 1 , . . . = 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, . . .
is the number of: properly nested sequences of pairs of parentheses; rooted ordered binary trees
with + 1 leaves; triangulations of a convex ( + 2)-gon.
Derangements . Number of permutations of = 0, 1, 2, . . . elements without xed points is
Stirling numbers of 1 kind . ,[ is] (1) times the number of permutations of elements
(, 0) = (0, ) = 0.
3
n/k
0
1
2
3
4
5
6
7
8
9
=1
=6
=3
24
=50
=5040
40320
=6
11
n/k
0
1
2
3
4
5
6
7
8
9
10
=225
13068
=13132
=109584
=10
35
274
=1764
720
118124
=15
6769
=1960
=67284
non-empty subsets.
( )
( ) .
(1)
=0
85
=735
1624
into exactly
{ }
=21
175
322
22449
=4536
=120
1
!
{ }
=28
546
=36
elements
= , = 1,1 + 1, ; ,1 = , = 1.
15
25
10
31
90
65
15
63
301
350
140
21
127
966
1701
1050
266
28
255
3025
7770
6951
2646
462
36
511
9330
34105
42525
22827
5880
750
45
10
9 10
Bell numbers
the number of partitions of elements. 0 , . . . = 1, 1, 2, 5, 15, 52, 203, 877, . . .
( .) is
+1 = =0 = +1
=1 , . Bell triangle: = ,1 = 1,1 , , = 1,1 + ,1 .
Eulerian numbers . (, ) = is the number of permutations with exactly descents ( : <
+1 ) / ascents ( > +1 ) / excedances ( > ) / + 1 weak excedances ( ).
Formula: (, ) = ( + 1)( 1, ) + ( )( 1, 1). (, 0) = (, =1) = 1.
( )
+1
(, ) =
( + 1 ) .
=0 (1)
Double factorial . Permutations of the multiset {1, 1, 2, 3, . . . , } such that for each
, all the num
bers between two occurrences of in the permutation are greater than . (2 1)!! =
=1 (2 1).
Eulerian numbers of 2 kind
factorial, number of all such permutations
. Related to Double
1
that have exactly ascents.
=
(2
1)
+ ( + 1) 1
.
=1
0
(
)
Multinomial
theorem . (1 + + ) =
1 1 . . . , where 0 and
= .
1 ,...,
( )
!
= (1 , . . . , ) = 1 !... ! . (, . . . , , , . . . ) = ( + + , , . . . ) (, . . . , )
1 ,...,
Necklaces and bracelets Necklace of length is an equivalence class of n-character strings
over an
1
/
alphabet of size , taking all rotations as equivalent. Number of necklases: () =
()
|
Bracelet is
{ a necklace such that strings may also be equivalent under reection. Number of bracelets:
1
() + 14 ( + 1) /2 if is even
() = 21
() + 12 (+1)/2
if is odd
2
An aperiodic necklace of length is an equivalence class of size , i.e., no two distinct rotations of a
1
/
necklace from such class are equal. Number of aperiodic necklaces: () =
.
| ()
Each aperiodic necklace contains a single Lyndon word. Lyndon word is -character string over
an alphabet of size
rotations.
and which is the minimum element in the lexicographical ordering of all its
and
< .
Burnsides
lemma .
|/| =
Let ()
1
||
be
4
The number of orbits under group
's
action on set
:
of xed points.)
1
||
().
int bit[M],n;
void update(int x, int v) { while( x <= n ) { bit[x] += v; x += x & -x; } }
int sum(int x) { int ret=0; while(x>0){ ret += bit[x]; x -= x & -x; } return ret; }
BIT 2D
int bit[M][M], n;
int sum( int x, int y ){
int ret = 0;
while( x > 0 ){
int yy = y; while( yy > 0 ) ret += bit[x][yy], yy -= yy & -yy;
x -= (x & -x);
}
return ret ;
}
void update(int x , int y , int val){
int y1;
while (x <= n){
y1 = y;
while (y1 <= n){ bit[x][y1] += val; y1 += (y1 & -y1); }
x += (x & -x);
}
}
RMQ DP
}
return d[ id ].ans;
}
int query( int l, int r, int id = 0 ) {
if( l > r ) return 0;
if( d[id].l == l && d[id].r == r ) return d[id].ans;
else {
int bar = (d[id].r-d[id].l) / 2 + d[id].l;
int left = 0, right = 0;
if( l <= bar ) {
if( r <= bar ) left = query( l, r, d[id].next_l );
else {
left = query( l, bar, d[id].next_l );
right = query( bar+1, r, d[id].next_r );
}
}else right = query( l, r, d[id].next_r );
return max( left, right );
}
}
struct unionfind {
int p[MAX], r[MAX]; // r contains the population
unionfind() { REP(i,MAX) p[i] = i, r[i] = 1; }
int find( int x ) { if( p[x] == x ) return x; else return p[x] = find( p[x] ); }
void Union(int x, int y) {
int px = find( x ), py = find( y );
if( px == py ) return; //already joined
if( r[ px ] < r[ py ] ) p[px] = py, r[py] += r[px];
else p[ py ] = px, r[px] += r[py];
}
};
misofs tree
int tree[17][65536];
void insert(int x) { for (int i=0; i<17; i++) { tree[i][x]++; x/=2; } }
void erase(int x) { for (int i=0; i<17; i++) { tree[i][x]--; x/=2; } }
int kThElement(int k) { int a=0, b=16;
while (b--) { a*=2; if (tree[b][a]<k) k-=tree[b][a++]; }
return a; }
Treaps
}
int queryrangekth(int &x, int a1, int a2, int k) {
a1 = find(x, a1); a2 = find(x, a2);
assert(a1 && a2);
int a,b,c; split(x,a1,a,b); split(b,a2,b,c);
int ret = findkth(b,k);
x = merge(a, merge(b,c));
return Value(ret);
}
is any solution, then all solutions are given by (, ) = (0 + , 0 ), Z. To nd some solution
2
If 1 (mod ) or
1 (mod ) for some 0 1, then is a probable prime. With
32
bases 2, 7 and 61, the test indenties all composites below 2 . Probability of failure for a random
Let
is at most 1/4.
Pollard- .
+1 = 2 1 (mod )
. Test gcd(, 2 + 2 ) as possible
's factors for = 0, 1, . . . Expected time to nd a factor: ( ), where is smallest prime power
1/4
in 's factorization. That's (
) if you check = as a special case before factorization.
Fermat primes . A Fermat prime is a prime of form 22 + 1. The only known Fermat primes are
+1 1
1
1
Number/sum of divisors . (1 . . . ) = =1 ( + 1). (1 . . . ) = =1 1 . () =
+1) 1
(
=1
Choose random
1 ,
and let
()() gcd(,)
.
(gcd(,))
()
.
( ) = 1 ( 1).
() =
() =
( ) = .
Eulers theorem
1 (mod ), if gcd(, ) = 1.
Wilsons theorem . is prime i ( 1)! 1 (mod ).
Mobius function . (1) = 1. () = 0, if is not squarefree. () = (1) ,
of
is the
product
, () = | (),
if
then () =
, and vice versa.
() = |
| () ( )
If is multiplicative, then
| () () =
| (1 ()),
Legendre symbol
residue modulo
. If
and
is an odd prime,
Z,
then
Jacobi symbol .
If
Primitive roots
. If the order of
= 11
is odd, then
( )
() .
() = 1.
| () () =
| (1 + ()).
( )
( )
=1
equals
0,
if
|; 1
if
is a quadratic
1
2
= ( ) (mod ).
( )
has a primitive root i is one of 2, 4, , 2 , where is an odd prime. If has a primitive root
, then for all coprime to , there exists unique integer = ind () modulo (), such that
(mod ). ind () has logarithm-like properties: ind(1) = 0, ind() = ind() + ind().
If is prime and is not divisible by , then congruence (mod ) has gcd(, 1) solutions
(1)/ gcd(,1)
if
1 (mod ), and no solutions otherwise. (Proof sketch: let be a primitive root,
Discrete logarithm problem . Find from (mod ). Can be solved in ( ) time and
space with a meet-in-the-middle trick. Let = , and = . Equation becomes
(mod ). Precompute all values that the RHS can take for = 0, 1, . . . , 1, and brute force on
modulo
(min
the LHS, each time checking whether there's a corresponding value for RHS.
Pythagorean triples .
2
2
2
Integer solutions of + = All relatively prime triples are given by:
= 2, = 2 2 , = 2 + 2 where > , gcd(, ) = 1 and (mod 2). All other
+ 2
2
2
2
triples are multiples of these. Equation + = 2 is equivalent to (
) + (
)2 = 2 .
2
2
1
(1)(1) numbers
2
Extended GCD
not
of form
pii egcd( LL a, LL b ) { //
if( b == 0 ) return pii(
else {
pii d = egcd( b, a %
return pii( d.y, d.x
}
}
GCD
General EGCD
Phi
LL power( LL a, LL b, LL mod ) {
LL x = 1, y = a;
while( b ) {
if( b&1 ) x *= y, x %= mod;
y *= y, y %= mod, b/=2;
}
return x%mod;
}
Rabin-Miller
Sieve prime
10
Sieve totient
FOR(i,1,M) f[i] = i;
FOR(n,2,M) if( f[n] == n ) for(int k=n; k<=M; k+=n) f[k] *= n-1, f[k] /= n;
11
}
REP(i,n) pos[rank[i]]=i;
}
void get_lcp(int n) {
lcp[0]=0;
int h=0;
REP(i,n) if(rank[i]) {
int j=pos[rank[i]-1];
while(i+h<n && j+h<n && str[i+h] == str[j+h]) h++;
lcp[rank[i]]=h;
if(h)h--;
} }
//slower version of SA, also works with get_lcp
struct data {
int nr[2], p;
bool operator<(const data &v)const{ return nr[0] < v.nr[0] || ...;}
bool operator==(const data &v)const{return nr[1]==v.nr[1]&&nr[0]==v.nr[0];}
} L[MAXN];
int P[MAXLG+2][MAXN], pos[MAXN], rank[MAXN];
int suffix_array(char *A, int N)
{
int step,cnt;
REP(i,N) P[0][i] = A[i];
for(step=1,cnt=1;cnt/2<N;cnt*=2,step++) {
REP(i,N) L[i]=(data){P[step-1][i],(i+cnt<N)?P[step-1][i+cnt]:-1,i};
sort(L,L+N);
REP(i,N) P[step][L[i].p] = i && L[i]==L[i-1]? P[step][L[i-1].p]:i;
}
REP(i,N) rank[L[i].p]=i;
REP(i,N) pos[rank[i]]=i;
return step-1;
}
Aho-Corasick
#define NC 26
#define NP 10005
#define M 100005
#define MM 500005
char a[M];
char b[NP][105];
int nb, cnt[NP], lenb[NP], alen;
int g[MM][NC], ng, f[MM], marked[MM];
int output[MM], pre[MM];
#define init(x) {REP(_i,NC)g[x][_i] = -1; f[x]=marked[x]=0; output[x]=pre[x]=-1; }
void match() {
ng = 0;
init( 0 );
// part 1 - building trie
REP(i,nb) {
cnt[i] = 0;
int state = 0, j = 0;
while(g[state][b[i][j]] != -1 && j < lenb[i]) state = g[state][b[i][j]], j++;
12
}
// part 2 - building failure function
queue< int > q;
REP(i,NC) if( g[0][i] != -1 ) q.push( g[0][i] );
while( !q.empty() ) {
int r = q.front(); q.pop();
REP(i,NC) if( g[r][i] != -1 ) {
int s = g[r][i];
q.push( s );
int state = f[r];
while( g[state][i] == -1 && state ) state = f[state];
f[s] = g[state][i] == -1 ? 0 : g[state][i];
}
}
// final smash
int state = 0;
REP(i,alen) {
while( g[state][a[i]] == -1 ) {
state = f[state];
if( !state ) break;
}
state = g[state][a[i]] == -1 ? 0 : g[state][a[i]];
if( state && output[ state ] != -1 ) marked[ state ] ++;
}
// counting
REP(i,ng+1) if( i && marked[i] ) {
int s = i;
while( s != 0 ) cnt[ output[s] ] += marked[i], s = f[s];
}
KMP
int f[ len ];
f[0] = f[1] = 0;
FOR(i,2,len) {
int j = f[i-1];
while( true ) {
if( s[j] == s[i-1] ) { f[i] = j + 1; break;
}else if( !j ) { f[i] = 0; break;
}else j = f[j];
}
}
i = j = 0;
while( true ) {
13
Permutation index
function TarjanOLCA(u)
MakeSet(u); u.ancestor := u;
for each v in u.children do
TarjanOLCA(v); Union(u,v); Find(u).ancestor := u;
u.colour := black;
for each v such that {u,v} in P and v.color==black do
print "LCA", u, v, Find(v).ancestor
procedure tarjan(v)
index = count; v.lowlink = count++; S.push(v);color[v] = 1;
for all (v, v2) in E do
if (!color[v2])
tarjan(v2); v.lowlink = min(v.lowlink, v2.lowlink);
else if (color[v2]==1)
v.lowlink = min(v.lowlink, v2.lowlink);
if (v.lowlink == index)
do { v2 = S.top(); S.pop(); print v2; color[v2]=2; } while (v2 != v);
for all v in V do if(!color[v]) tarjan(v);
int grid[M][M], l[M], r[M], seen[M], rows, cols; bool lT[M], rT[M];
bool dfs(int x) {
if( seen[x] ) return false;
seen[x] = true;
Rep(i,cols) if( grid[x][i] ) if( r[i] == -1 || dfs( r[i] ) )
{ r[i] = x, l[x] = i; return true; }
return false;
}
int bpm() {
SET( l, -1 ); SET( r, -1 ); int ret = 0;
Rep(i,rows) { SET( seen, 0 ); if( dfs( i ) ) ret ++; }
return ret;
}
void konigdfs(int x) {
if( !lT[x] ) return; lT[x] = 0;
Rep(i,cols) if(grid[x][i] && i != l[x])
{ rT[i] = true; if( r[i] != -1) konigdfs(r[i]); }
}
int konig() { SET(lT,1); SET(rT,0); Rep(i,rows) if(l[i]==-1) konigdfs(i);}
Bellman-Ford
VI e[M], c[M];
int n, d[M], p[M];
int inf = 1<<29;
int bford( int s, int f ) {
REP(i,n) d[i] = i == s ? 0 : inf, p[i] = -1;
REP(_,n-1) {
bool done = 1;
REP(i,n) REP(j,e[i].sz) {
int u = i, v = e[i][j], uv = c[i][j];
if( d[u] + uv < d[v] ) d[v] = d[u] + uv, p[v] = u, done = 0;
}
if( done ) break;
}
REP(i,n) REP(j,e[i].sz) {
int u = i, v = e[i][j], uv = c[i][j];
if( d[u] + uv < d[v] ) return -33;
}
if( d[f] == inf ) return -33;
return d[f];
}
#define M 750
int nr, nc, o = 355, source = 740, sink = 741;
vector<int> edge[M];
int cap[M][M];
bool vis[M];
void init() {
REP(i,M) edge[i].clear();
SET( cap, 0 );
14
15
}
void add( int a, int b, int c, int d ) {
edge[a].pb(b), edge[b].pb(a);
cap[a][b] += c, cap[b][a] += d;
}
int dfs( int src, int snk, int fl ) {
if( vis[src] ) return 0;
if( snk == src ) return fl;
vis[src] = 1;
REP(i,edge[src].sz) {
int v = edge[src][i];
int x = min( fl, cap[src][v] );
if( x > 0 ) {
x = dfs( v, snk, x );
if( !x ) continue;
cap[src][v] -= x;
cap[v][src] += x;
return x;
}
}
return 0;
}
int flow( int src, int snk ) {
int ret = 0;
while( 1 ) {
SET( vis, 0 );
int delta = dfs( src, snk, 1<<30 );
if( !delta ) break;
ret += delta;
}
return ret;
}
16
int st = 0, en = 0;
Q[en++] = src;
while( st < en ) {
int u = Q[ st++ ];
for(int e = fin[u]; e >= 0; e = next[e] ) {
int v = to[e];
if( flow[e] < cap[e] && dist[v] == -1 ) {
dist[v] = dist[u] + 1;
Q[en++] = v;
}
}
}
return dist[snk] != -1;
}
int dfs(int u, int fl) {
if( u == snk ) return fl;
for( int& e = pro[u]; e >= 0; e = next[e] ) {
int v = to[e];
if( flow[e] < cap[e] && dist[v] == dist[u]+1 ) {
int x = dfs( v, min( cap[e] - flow[e] , fl ) );
if( x > 0 ) {
flow[ e ] += x, flow[ e^1 ] -= x;
return x;
}
}
}
return 0;
}
LL dinic() {
LL ret = 0;
while( bfs() ) {
FOR(i,1,nnode) pro[i] = fin[i];
while( 1 ) {
int delta = dfs( src, inf );
if( !delta ) break;
ret += delta;
}
}
return ret;
}
struct edge {
int to, cost, cap;
int back;
};
edge E[N*N];
17
//
//
//
//
//
//
18
//
}
// remember to add -cost in the opposite direction
void add( int u, int v, int uv, int vu, int fuv, int fvu ) {
int a = nE, b = nE+1;
nE += 2;
E[ a ].to = v, E[ a ].cost = uv, E[ a ].cap = fuv, E[ a ].back = b;
E[ b ].to = u, E[ b ].cost = vu, E[ b ].cap = fvu, E[ b ].back = a;
e[ u ].pb( a ), e[ v ].pb( b );
}
Eulers theorem .
where
is the
+ = 2 for a 3D polyhedron.
Vertex covers and independent sets . Let , , be a max matching, a min vertex cover, and
a max independent set. Then | | || = ||, with equality for bipartite graphs. Complement
of an MVC is always a MIS, and vice versa. Given a bipartite graph with partitions (, ), build
a network: connect source to , and to sink with edges of capacities, equal to the corresponding
nodes' weights, or 1 in the unweighted case. Set capacities of the original graph's edges to the innity.
Let (, ) be a minimum - cut. Then a maximum(-weighted) independent set is = ()( ),
and a minimum(-weighted) vertex cover is = ( ) ( ).
Matrix-tree theorem . Let matrix = [ ], where is the number of multiedges between and
, for = , and = deg . Number of spanning trees of a graph is equal to the determinant of a
matrix obtained by deleting any -th row and -th column from .
vertices,
+ = 1 + ,
Euler tours .
Euler tour in an undirected graph exists i the graph is connected and each vertex has
an even degree. Euler tour in a directed graph exists i in-degree of each vertex equals its out-degree,
and underlying undirected graph is connected.
match
with
add to
to
If
: let
is free,
Store cut-of-the-phase (the cut between the last added vertex and rest of the graph), and merge the
two vertices added last. Repeat until the graph is contracted to a single vertex. Minimum cut is one
of the cuts-of-the-phase.
2-SAT . Build an implication graph with 2 vertices for each variable for the variable and its inverse;
add edges
(, )
and
(, ).
and
are in distinct
To nd a satisable assignment, consider the graph's SCCs in topological order from
sinks to sources (i.e. Kosaraju's last step), assigning `true' to all variables of the current SCC (if it
hasn't been previously assigned `false'), and `false' to all inverses.
| ()|.
Build a matrix
has a perfect
is identically zero. Testing the latter can be done by computing the determinant for a few random
values of
, 's
to
smallest label, and output its only neighbor's label, until only one edge remains. The sequence has
length
and
2.
Two isomorphic trees have the same sequence, and every sequence of integers from
vertices is 2 .
Erdos-Gallai theorem
19
{1 , 2 , . . . , }
, with 1 1 2
0 is a
degree sequence of some undirected simple graph i
is even and 1 + +
( 1) + =+1 min(, ) for all = 1, 2, . . . , 1.
. A sequence of integers
(, ):
= min{ 0 : }. is losing i () = 0.
Misre Nim . A position with pile sizes 1 , 2 , . . . , 1, not all equal to 1, is losing i 1 2
= 0 (like in normal nim.) A position with piles of size 1 is losing i is odd.
.
() = mex({() : (, ) }),
where mex()
Geometry
( (2
2 )
Geodistance
(2
2
Let = (0, 0) centers are ( (
2
))/ where = 2( ).
+ 2 ) (2 + 2 ))/
and
double gdist ( double a_lat, double b_lat, double a_long, double b_long ) {
return acos( cos(a_lat) * cos(b_lat) * cos(a_long - b_long) + sin(a_lat) * sin(b_lat));
} // dont forget to multiply radius with it! ;)
Point in a triangle
is number of lattice
Projection
of point
Projection of
(0 , 0 )
is
.
line + = is (0 , 0 ) +
1
(, ).
2 +2
onto line
onto
Segment-segment intersection .
1
(, ), where
2 +2
= 0 0 .
of the other segment, or each segment straddles the line, containing the other segment ( straddles
line
if
and
20
Angular bisector
+ ||
.
is line , where = ||
+ ++
+
Center of incircle of triangle is at the intersection of angular bisectors, and is
++
2
, where , , are lengths of sides, opposite to vertices , , . Radius = ++ .
++
Counter-clockwise rotation around the origin . (, ) ( cos sin , sin + cos ).
90-degrees counter-clockwise rotation: (, ) (, ). Clockwise: (, ) (, ).
3D rotation by ccw angle around axis n: r = r cos + n(n r)(1 cos ) + (n r) sin
Plane equation from 3 points . (, , ) = , where is normal: = ( ) ( ).
3D figures
Sphere
Spherical section
Pyramid
Cone
Area of a simple
of angle
= 34 3 , surface area = 42
= sin cos , = sin sin , = cos , [, ], [0, ]
2
Volume = ( /3), surface area = 2
1
Volume =
3
1
2
Volume = , lateral surface area = 2 + 2
3
1
1
polygon . 2 =0 ( +1 +1 ), where = 0 , = 0 .
Volume
Winding number .
Shoot a ray from given point in an arbitrary direction. For each intersection
Convex Hull
+1
if clockwise.
Trigonometric identities
21
= sin = sin = 2 .
Law of sines:
sin
2
2
2
Law of cosines: = + 2 cos .
Law of tangents:
tan[ 21 (+)]
tan[ 12 ()]
Inscribed/outscribed circles: =
, =
4
++
( )( )( ), = 2 .
Heron:
's
2
++
2
2(cot +cot )
22
}
return fabs(dist);
}
struct Line { double A,B,C; };//Ax + By = C
Line makeline(point2d a1, point2d a2)
{
Line ret = (Line){ a2.y-a1.y, a1.x-a2.x };
ret.C = ret.A * a1.x + ret.B * a1.y;
return ret;
}
double dist(Line l, point2d p)
{
return fabs(p.x * l.A + p.y * l.B - l.C)/sqrt(l.A*l.A+l.B*l.B);;
}
Line rot90(Line l, point2d p)
{
Line ret = (Line){ -l.B, l.A };
ret.C = ret.A * p.x + ret.B * p.y;
return ret;
}
point2d intersect(Line l1, Line l2)
{
double det = l1.A*l2.B - l2.A*l1.B;
if(fabs(det) < eps) det=0;//zero means parallel
return (point2d) { (l2.B*l1.C - l1.B*l2.C)/det, (l1.A*l2.C - l2.A*l1.C)/det};
}
//for segment segment intersection, check additionally
//min(x1,x2) <= x <= max(x1,x2)
//min(y1,y2) <= x <= max(y1,y2)
bool segmentsIntersect( point2d A, point2d B, point2d C, point2d E )
{
point2d in = intersect( makeline(A,B), makeline(C,E) );
return linePointDist(A,B,in,true) < eps && linePointDist(C,E,in,true) < eps;
}
// get a line passing between two points
Line getmidline(point2d a, point2d b)
{
point2d mid(a+b); mid.x/=2; mid.y/=2;
return rot90( makeline(a,b), mid );
}
//reflect a point into its "mirror" with repect to a line
point2d reflectPoint(Line l, point2d p)
{
Line r = rot90(l, p);
point2d Y=intersect(l,r);
return Y-(p-Y);
}
23
Blossoms
int lf[205],mat[205][205],n;
VVI adj;
VI vis,inactive,match;
24
int N;
bool dfs(int x,VI &blossom){
if(inactive[x]) return false;
int i,y;
vis[x] = 0;
for(i = adj[x].size()-1;i>=0;i--){
y = adj[x][i];
if(inactive[y]) continue;
if(vis[y]==-1){
vis[y] = 1;
if(match[y]==-1 || dfs(match[y],blossom)){
match[y] = x;
match[x] = y;
return true;
}
}
if(vis[y]==0 || blossom.size()){
blossom.push_back(y);
blossom.push_back(x);
if(blossom[0]==x){
match[x] = -1;
return true;
}
return false;
}
}
return false;
}
bool augment(){
VI blossom,mark;
int i,j,k,s,x;
for(i = 0;i<N;i++){
if(match[i]!=-1) continue;
blossom.clear();
vis = VI(N+1,-1);
if(!dfs(i,blossom)) continue;
s = blossom.size();
if(s==0) return true;
mark = VI(N+1,-1);
for(j = 0;j<s-1;j++){
for(k = adj[blossom[j]].size()-1;k>=0;k--)
mark[adj[blossom[j]][k]] = j;
}
for(j = 0;j<s-1;j++){
mark[blossom[j]] = -1;
inactive[blossom[j]] = 1;
}
adj[N].clear();
for(j = 0;j<N;j++){
25
if(mark[j]!=-1)
adj[N].pb(j),adj[j].pb(N);
}
match[N] = -1;
N++;
if(!augment()) return false;
N--;
for(j = 0;j<N;j++){
if(mark[j]!=-1) adj[j].pop_back();
}
for(j = 0;j<s-1;j++){
inactive[blossom[j]] = 0;
}
x = match[N];
if(x!=-1){
if(mark[x]!=-1){
j = mark[x];
match[blossom[j]] = x;
match[x] = blossom[j];
if(j & 1)
for(k = j+1;k<s;k+=2) {
match[blossom[k]] =
match[blossom[k+1]]
}
else
for(k = 0;k<j;k+=2) {
match[blossom[k]] =
match[blossom[k+1]]
}
}
}
return true;
}
return false;
blossom[k+1];
= blossom[k];
blossom[k+1];
= blossom[k];
26
inactive = VI(2*N+1);
while(augment()) ret++;
return ret;
Binary search
/*LE*/
while(l <= h){ m = (l+h) / 2; if(works(m))
return l-1;
/*GE*/
while(l <= h){ m = (l+h) / 2; if(works(m))
return h+1;