You are on page 1of 25

ACM ICPC Reference, page 1

University of So Paulo

ACM ICPC Reference


University of So Paulo
May 13, 2015
Contents
1

Template

Lista de bugs e recomendaes

Numbers and Number Theory


Extended Euclids Algorithm (Bzouts Theorem)
Chinese Remainder Theorem . . . . . . . . . . .
MillerRabin (Primality test) . . . . . . . . . . .
Pollards Rho (Factorization) . . . . . . . . . . . .
Brents Algorithm (Cycle detection) . . . . . . . .
Luccas Theorem . . . . . . . . . . . . . . . . . .
Simpsons Rule for numerical integration . . . . .
Lagrange Interpolating Polynomial . . . . . . . .
Farey Sequence . . . . . . . . . . . . . . . . . . .
Eulers Totient Function . . . . . . . . . . . . . .
Pillais arithmetical function . . . . . . . . . . . .
Gaussian Elimination . . . . . . . . . . . . . . . .
Fast Fourier Transform . . . . . . . . . . . . . . .
Least Squares Method . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

2
2
2
3
3
4
4
4
4
4
5
5
5
5
6

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

Combinatorics
Catalan Numbers . . . . . . . . . . .
Stirling Numbers of the First Kind .
Stirling Numbers of the Second Kind
Bell Numbers . . . . . . . . . . . . .
Narayana Numbers . . . . . . . . . .
The Twelvefold Way . . . . . . . . .
Partition (number theory) . . . . . .
Derangement (Desarranjo) . . . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

6
6
6
6
7
7
7
7
7

Geometry 2D
Point Structure . . . . . . .
Auxiliary Functions . . . . .
Convex Hull . . . . . . . . .
Convex Polygon Intersection
Polygon-Line Intersection . .
Polygon Triangulation . . .
Closest Pair . . . . . . . . .
Crosses Half-Plane . . . . .
N segments Intersection . .
Circle Structure . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

8
8
8
9
9
9
10
10
11
11
12

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

Circle Intersection . . . . .
Circle Union . . . . . . . .
Minimum Spanning Circle
Circle-Polygon Intersection

.
.
.
.

12
12
13
13

Geometry 2D - Integer
Geometry Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13
13

Geometry 3D
Geometry 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14
14

Graph
ErdsGallai theorem . . . . . . . . . . . . . . . . . . .
Stable Marriage . . . . . . . . . . . . . . . . . . . . . .
Dinic maxflow . . . . . . . . . . . . . . . . . . . . . . .
Min-cost maxflow . . . . . . . . . . . . . . . . . . . . .
Finding one solution for 2SAT . . . . . . . . . . . . . .
Stoer-Wagner algorithm for global mincut . . . . . . . .
Maximum matching in generic graph . . . . . . . . . .
Tarjans algorithm for Strongly Connected Components
Articulation point and Bridges . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

Strings
Aho-Corasick . . . . . . . . . .
Manachers algorithm for finding
Sux array . . . . . . . . . . .
Knuth-Morris-Pratt algorithm .
Hash . . . . . . . . . . . . . . .
Z-algorithm . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

15
15
15
16
17
18
18
18
19
20

. . . . . . . . . . . . . . . . .
longest palindromic substring
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

20
20
20
21
22
22
22

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

23
23
23
23
25

10 Data structures
Static Range Minimum Query . . .
2D Longest Increasing Subsequence
Treap . . . . . . . . . . . . . . . .
KD-Tree . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

ACM ICPC Reference, page 2

University of So Paulo

Template

m. update ( trimmed )
hash = m. h e x d i g e s t ( ) [ : 4 ]
p r i n t "%s %s "%(hash , s a f e ) ,

iniciodeprova.txt
###### Emacs c o n f i g ######

( s e t q d e f a u l t i n d e n t t a b s mode n i l )
( setq c basic o f f s e t 4)
( g l o b a l linum mode 1 )
( e l e c t r i c i n d e n t mode 1 )
( g l o b a l u n s e t key "\C z " )
( g l o b a l u n s e t key "\C x\C z " )
( g l o b a l h l l i n e mode 1 )
( s e t f a c e background d e f a u l t "#202020")
( s e t f a c e f o r e g r o u n d d e f a u l t " White " )
( s e t f a c e background h l l i n e "#003399")

###### v i m r c ######
f i l e t y p e p l u g i n on
f i l e t y p e i n d e n t on
s e t number
s y n t a x on
s e t s h i f t w i d t h =4
s e t t a b s t o p =4
colorscheme
evening

2b74
916e
916e
a947
f69c
dd8c
40f4
a04e
2546
7c08
7c08
dd14
45e9
a13c
2b93

#include <bits/stdc++.h>
using namespace std;
#define
#define
#define
#define
#define
#define
#define

Lista de bugs e recomendaes


Reler enunciado e pedir clarifications (evitar explicar o enunciado para outra pessoa).
Verificar overflows.
Ver se o 1 to infinito quanto parece e se o eps to pequeno quanto o necessrio.
Comparao de ponto flutuante com tolerncia.
Verificar se o grafo pode ser desconexo.
Verificar se pode haver self-loops, arestas com peso negativo ou ligando um mesmo par de vrtices.
Cuidar de casos com pontos coincidentes e pontos colineares.
Igualdade dentro de if (a == b ao invs de a = b)
Verificar trechos de cdigo quase iguais ou copy-pasted.
Verificar tamanho de vetores.
Overflow em shift (1ll << 40 ao invs de 1 << 40)
No usar variveis com nome min, max, next.
Verificar inicializao de variveis.
Verificar casos extremos, muito pequenos ou muito grandes, caso zero.
Cuidar de imprecises ao subtrair nmeros quase iguais.
Tomar cuidado com resto de diviso envolvendo nmeros negativos.
No comparar unsigned int (.size()) com int negativo.

Numbers and Number Theory

Extended Euclids Algorithm (Bzouts Theorem)

debug(x...) fprintf(stderr,x)
pb push_back
f(i,x,y) for(int i=x; i<y; i++)
quad(x) ((x)*(x))
clr(x,y) memset(x,y,sizeof x)
fst first
snd second

typedef pair<int,int> pii;


typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

d41d //O valor retornado eh gcd(a,b) = ax + by


a674 ll gcd_extended(ll a, ll b, ll &x, ll &y) {
c994
if (a == 0) { x = 0, y = 1; return b; }
7459
ll xx, yy, d = gcd_extended(b%a, a, xx, yy);
8d0e
x = yy-(b/a)*xx, y=xx;
5bdc
if (d < 0) {d = -d; x = -x; y = -y; }
9d45
return d;
1255 }

Chinese Remainder Theorem


../hashify.py
import hashlib , sys
m = h a s h l i b . md5 ( )
for l i n e in sys . stdin . readlines ( ) :
safe = line
i f l i n e . f i n d ( " / / " ) !=
1:
line = line [ : line . find ("//")]
trimmed = l i n e . r e p l a c e ( " " , " " ) . r e p l a c e ( " \ n " , " " ) . r e p l a c e ( " \ t " , " " )

Suppose m0 , m1 , ..., mk 1 are positive integers that are pairwise coprime. Then, for any given sequence of integers
a1 , a2 , ..., ak 1 , there exists an integer X solving the following system of simultaneous congruences.
X a0

(mod m0 )

X a1

(mod m1 )
.
.
.

X ak

(mod mk

1)

ACM ICPC Reference, page 3

University of So Paulo

Furthermore, all solutions X of this system are congruent modulo the product, M = m0 m1 ...mk
solution for this system is:
Pk 1 M
M
X =
1, m
bi 1 (mod mi ).
i=0 m bi ai , where bi is a integer, such that: 8i, 0 i k
i

1.

A possible

OBS.: Observaes sobre chinesResto.cpp.

No usa o algoritmo mostrado acima;


Se o sistem tem soluo, armazena em X o valor da menor solucao positiva e retorna true. Retorna false caso
contrrio;
Complexidade : O(k * log( maxm[i] ), sem usar mulmod;
CUIDADO: l = lcm(m[0],m[1],...,m[k-1]) cuidado para no estourar long long;
CUIDADO: os valores do vetor a[0...k-1] so alterados;
CUIDADO: assume que k > 1;

9b9c
1c31
1c31
1c31
839d
28c3
d300
82f4
bec2
18ca
12b8
12b8
12b8
ce3b
9e85
9e85
8818
ad2e
d092
e610
aa7c
9043
a3a9
5d5c
062f
bba8
01a9
ea7e

ll gcd(ll a, ll b) { return a?gcd(b%a, a):abs(b); }


ll lcm(ll x, ll y) { return (x&&y) ? abs(x) / gcd(x,y) * abs(y): 0; }
//(a*b) % mod => O(log b)
ll mulmod(ll a, ll b, ll mod) {
if (b < 0) return mulmod(a, (b%mod + mod)%mod, mod);
if (b == 0) return 0LL;
ll ans = (2LL * mulmod(a, b/2, mod)) % mod;
if (b%2 == 0) return ans;
return (ans + a) % mod;
}
//para td i, (0 <= i < k), x = a[i] ( mod m[i])
ll a[MAX], m[MAX];
bool chines_resto(ll &X, int k) {
//Assume que k >= 1
ll d, z, w, l = m[0];
X = (a[0] % m[0] + m[0]) % m[0];
for (int i = 1; i < k; i++) {
a[i] %= m[i];
d = gcd_extended(l, m[i], z, w);
if ( (a[i]-X) % d != 0) return false;
X += l*z*((a[i]-X)/d); //Pode usar mulmod(), pra nao estourar ll
l = lcm(l, m[i]);
X = ((X%l) + l) % l;
}
return true;
}

MillerRabin (Primality test)


a288 llu llrand() { llu a = rand(); a<<= 32; a+= rand(); return a;}
67b7 int is_probably_prime(llu n) {
61d5
if (n <= 1) return 0;
2ecf
if (n <= 3) return 1;
a093
llu s = 0, d = n - 1;
0127
while (d % 2 == 0) {

028a
1c22
6cab
fc88
9d61
e9cb
6e13
1479
569b
7ee2
74f4
344f
429d
c1fc
85bd
03b9
abcb
8fad
78e3 }

d/= 2; s++;
}
for (int k = 0; k < 64; k++) {
llu a = (llrand() % (n - 3)) + 2;
llu x = exp_mod(a, d, n);
if (x != 1 && x != n-1) {
for (int r = 1; r < s; r++) {
x = mul_mod(x, x, n);
if (x == 1)
return 0;
if (x == n-1)
break;
}
if (x != n-1)
return 0;
}
}
return 1;

Pollards Rho (Factorization)


295a
dd00
77b5
d711
410c
6200
72a6
7ba8
bf50
07a4
4ae0
0884
b528
6ac2
3fa3
aa26
d6b5
780e
7609
1f13
6468
0bcb
79c1
838b

llu rho(llu n) {
llu d, c = rand() % n, x = rand() % n, xx = x;
if (n % 2 == 0)
return 2;
do {
x = (mul_mod(x, x, n) + c) % n;
xx = (mul_mod(xx, xx, n) + c) % n;
xx = (mul_mod(xx, xx, n) + c) % n;
d = gcd(val_abs(x - xx), n);
} while (d == 1);
return d;
}
map <llu,int> F;
void factor(llu n) {
if (n == 1)
return;
if (is_probably_prime(n)) {
F[n]++;
return;
}
llu d = rho(n);
factor(d);
factor(n/d);
}

ACM ICPC Reference, page 4

University of So Paulo

Brents Algorithm (Cycle detection)

Lagrange Interpolating Polynomial

Let x0 2 S be an element of the finite set S and consider a function f : S ! S. Define

The Lagrange interpolating polynomial is the polynomial P (x) of degree (n


(x1 , y1 = f (x1 )), (x2 , y2 = f (x2 )), ..., (xn , yn = f (xn )), and is given by

fk (x) =

x,

k=0

f fk

1 (x)

k>0

P (x) =

n
X

1) that passes through the n points

yi Pi (x),

i=1

Clearly, there exists distinct numbers i, j 2 N, i 6= j, such that fi (x0 ) = fj (x0 ).


Let 2 N be the least value such that there exists j 2 N \ {} such that f (x0 ) = fj (x0 ) and let 2 N be the
least value such that f (x0 ) = f+ (x0 ).
Given x0 and f , this code computes and
applying the operator f O( + ) times and storing at most a
constant amount of elements from S.

where
Pi (x) =

n
Y
x
x
k=1 i

xk
xk

k6=j

Written explicitly,
P (x) =

(x
(x1

x2 )(x
x2 )(x1

x3 )...(x xn )
(x
y1 +
x3 )...(x1 xn )
(x2

x1 )(x
x1 )(x2

x3 )...(x xn )
y2 + ...
x3 )...(x2 xn )

(x
(xn

x1 )(x
x1 )(xn

x2 )...(x xn 1 )
yn .
x2 )...(xn xn 1 )

Luccas Theorem
For non-negative integers m and n and a prime p, the following congruence relation holds:
m
n

k
Y
mi

i=0

ni

Farey Sequence

(mod p),

Farey Sequence of order n is the sequence of completely reduced fractions between 0 and 1 which, when in lowest
terms, have denominators less than or equal to n, arranged in order of increasing size.
F1 = {0/1, 1/1}, F2 = {0/1, 1/2, 1/1}, F3 = {0/1, 1/3, 1/2, 2/3, 1/1}, ...

where
m = mk pk + mk 1 pk 1 + ... + m1 p + m0
and
n = nk pk + nk 1 pk 1 + ... + n1 p + n0
are the base p expansions of m and n respectively.

From this, we can relate the lengths of Fn and Fn

Simpsons Rule for numerical integration


Simpsons rule is a method for numerical integration, the numerical approximation of definite integrals.
b
a

f (x) dx

a
6

"

f (a) + 4f (

a+b
) + f (b)
2

Suppose that the interval [a, b] is split up in n subintervals, with n an even number. Then, the composite
Simpsons rule is given by:
Z

b
a

f (x) dx

n 1
n
"
2
2
X
X
h
f (x0 ) + 2
f (x2j ) + 4
f (x2j
3
j=1
j=1

Where xj = a + jh for j = 0, 1, ..., n 1, n, with h = (b


The above formula can also be written as:
Z

b
a

f (x) dx

using Eulers totient function '(n) :

|Fn | = |Fn
The asymptotic behaviour of |Fn | is : |Fn |

1)

+ f (xn )

a)/n (in particular, x0 = a and xn = b).

"
h
f (x0 ) + 4f (x1 ) + 2f (x2 ) + 4f (x3 ) + 2f (x4 ) + ... + 4f (xn
3

1)

+ f (xn )

d41d
d41d
d41d
d41d
e3cd
2e8e
8781
6ab6
dea7
7c2d
7c2d
12b6
12b6
d0f3
c77b
6cc1
6cc1
d737
877c
877c
0509

3n2
2

1|

+ '(n)

//gera a n-th sequencia de Farey


//conjunto de numeros racionais irredutiveis a/b, 0<=a<=b<=n && gcd(a,b)=1.
//Os valores sao armazenados em ordem cresecente em num[0..top-1]/den[0..top-1]
short num[10000000], den[10000000];
int top;
void Farey_sequence(int n) {
top = 0;
num[top] = 0, den[top] = 1;
top++;
build_sequence(0, 1, 1, 1, n);
num[top] = 1, den[top] = 1;
top++;
}
inline void build_sequence(int a1, int b1, int a2, int b2, int &n) {
if (b1+b2 > n) return;
build_sequence(a1, b1, a1+a2, b1+b2, n);

ACM ICPC Reference, page 5

University of So Paulo

c557
278a
278a
8330
f7c2 }

num[top] = a1+a2, den[top] = b1+b2;


top++;
build_sequence(a1+a2, b1+b2, a2, b2, n);

Eulers Totient Function


'(n) = n

p|n

'(mn) = '(m)'(n).

1
p

'(p.n) =

(p

1)'(n),

pn

p|n

p'(n),

d
, where d = gcd(m, n). N ote the special cases.
'(d)
k

'(p ) = p

1
p

'(d) = n;

d|n

Eulers theorem : if a and n are relatively prime then


a

'(n)

(mod n)

Pillais arithmetical function


P (n) :=

n
X

k=1

gcd(k, n) (n 2 N := {1, 2, ...})

P (n) =

X
d|n

d'(n/d) (n 2 N)

For every prime power pa , (a 2 N), P (pa ) = (a + 1)pa apa 1 .


P (n) is multiplicative, ie, for every integers a and b, such that gcd(a, b) = 1, P (ab) = P (a)P (b).
Let Paltern (n) be the alternating gcd-sum function. Let n 2 N and write n = 2a m, where a 2 N0 := {0, 1, 2, ....}
and m 2 N is odd. Then
Paltern (n) :=

n
X

( 1)

gcd(k, n) =

aP (m) =

Gaussian Elimination
Can be easily adapted to integers mod P, fractions and long doubles.

b94a
b94a
6d0c
c19b
c19b
33d8
bdd8
09a1

const int MAXN = 110;


typedef double Number;
const Number EPS = 1e-9;
Number mat[MAXN][MAXN];
int idx[MAXN];
// row index
int pivot[MAXN]; // pivot of row i

// Solves Ax = B, where A is a neq x nvar matrix and B is mat[*][nvar]


// Returns a vector of free variables (empty if system is defined,
// or {-1} if no solution exists)
// Reduces matrix to reduced echelon form
vector<int> solve(int nvar, int neq) {
for(int i = 0; i < neq; i++) idx[i] = i;
int currow = 0;
vector<int> freeVars;
for(int col = 0; col < nvar; col++) {
int pivotrow = -1;
Number val = 0;
for(int row = currow; row < neq; row++) {
if(fabs(mat[idx[row]][col]) > val + EPS) {
val = fabs(mat[idx[row]][col]);
pivotrow = row;
}
}
if(pivotrow == -1) { freeVars.push_back(col); continue; }
swap(idx[currow], idx[pivotrow]);
pivot[currow] = col;
for(int c = 0; c <= nvar; c++) {
if(c == col) continue;
mat[idx[currow]][c] = mat[idx[currow]][c] / mat[idx[currow]][col];
}
mat[idx[currow]][col] = 1;
for(int row = 0; row < neq; row++) {
if(row == currow) continue;
Number k = mat[idx[row]][col] / mat[idx[currow]][col];
for(int c = 0; c <= nvar; c++)
mat[idx[row]][c] -= k * mat[idx[currow]][c];
}
currow++;
}
for(int row = currow; row < neq; row++)
if(mat[idx[row]][nvar] != 0) return vector<int>(1, -1);
return freeVars;
}

if n is odd;

n,
2a

09a1
09a1
09a1
09a1
09a1
c993
b764
96b9
a12c
3bf0
43da
e8ad
45fb
c4e9
7188
ddf6
b465
0aab
f452
291f
d1de
d898
2e81
558c
e221
868e
1320
d2ac
f3af
68fa
ee55
aae1
95f1
f9ce
c884
b5d4
e4b2
19cf

a
a+2 P (n),

if n is even.

Fast Fourier Transform


If you are calculating the product of polynomials, dont forget to set the vectors size to at least the sum of
degrees of both polynomials, regardless of whether you will use only the first few elements of the array.

6dba
b9dc
b9dc
b9dc
6ca7
7ca9
7e69
e1c7

typedef complex<long double> Complex;


const long double PI = acos(-1.0L);
// Computes the DFT of vector v if type = 1, or the IDFT if type = -1
vector<Complex> FFT(vector<Complex> v, int type) {
int n = v.size();
while(n&(n-1)) { v.push_back(0); n++; }
int logn = __builtin_ctz(n);

ACM ICPC Reference, page 6

University of So Paulo

4d07
7df5
3e55
ba11
a97d
5e4f
1a64
48a4
c108
7a46
15e7
2b20
1085
8e81
66f2
a81b
c40c
b83f
a0e0
5d65 }

vector<Complex> v2(n);
for(int i=0; i<n; i++) {
int mask = 0;
for(int j=0; j<logn; j++) if(i&(1<<j)) mask |= (1<<(logn - 1 - j));
v2[mask] = v[i];
}
for(int s=0, m=2; s<logn; s++, m<<=1) {
Complex wm(cos(2.L * type * PI / m), sin(2.L * type * PI / m));
for(int k=0; k<n; k+=m) {
Complex w = 1;
for(int j=0; 2*j<m; j++) {
Complex t = w * v2[k + j + (m>>1)], u = v2[k + j];
v2[k + j] = u + t; v2[k + j + (m>>1)] = u - t;
w *= wm;
}
}
}
if(type == -1) for(Complex &c: v2) c /= n;
return v2;

It holds that:

h ni
k

For integers n

..

.
...

< g 0 , gn 1 >
< g 1 , gn 1 >
.
.
.
< g n 1 , gn 1 >

32
76
76
76
76
54

a0
a1
.
.
.
an

7
6
7
6
7=6
7
6
5
4

< f, g0 >
< f, g1 >
.
.
.
< f, gn 1 >

0,

It holds that:

1,

n=0

0,

n 6= 0

h ni

7
7
7
7
5

where x
and y are the mean value of x and y, respectively.

= (n

h0i

1)!;

h n i
nn
=
;
n 3
2
4

In the linear discrete case when g(x) = ax + b, a and b can also be found using the following equations:
Pn
y)
i=1 xi (yi
a = Pn
,
b = y a
x
x
)
i=1 xi (xi

h ni

counts the number of permutations of n elements with exactly k cycles.


k
The number of digraphs with n vertices and k cycles such that each vertex has in and out degree of 1.
k

...
...

Hn =

n
X
1
,
j
j=1

h ni
2

(k)

Hn

1,

k=0

0,

k 6= 0

h ni

h n i
n
=
;
n 1
2
= (n

1)!Hn

h ni

1;

k=0

1)

hn

h n i
1
= (3n
n 2
4
3

n h i
X
n

n
X
1
;
jk
j=1

= (n

1i
1)

n h i
X
n j

= n!;

j=k

1i
;
1

n
3

2
1)! Hn

1
(n
2

hn

;
(2)

Hn

hn + 1 i
k+1

n no

is the number of ways to partition an n-set into exactly k non-empty disjoint subsets up to a permutation of
k
the sets among themselves. It holds that:
n no

Combinatorics

1,
0,

n no
k

Catalan Numbers
n no

Cn is:
The number of balanced expressions built from n pairs of parentheses.
The number of paths in an n n grid that stays on or below the diagonal.
The number of words of size 2n over the alphabet = {a, b} having an equal number of a symbols and b
symbols containing no prefix with more a symbols than b symbols.
(starting with C0 ): 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440,
9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650,
1289904147324, 4861946401452...

Stirling Numbers of the Second Kind

2n
1 2n
(2n)!
=
=
n 1
n+1 n
n!(n + 1)!

is:

Let f, g0 , g1 , ..., gn 1 be given functions. The coecients of the function g(x) = a0 g0 (x)+a1 g1 (x)+...+an 1 gn 1 (x)
that best fits f (x) so that the inner product < f g, f g > is minimum is given by the system of equations below.
< g0 , g1 >
< g1 , g1 >
.
.
.
< gn 1 , g1 >

Stirling Numbers of the First Kind

Least Squares Method

< g0 , g0 >
< g1 , g0 >
.
.
.
< gn 1 , g0 >

2n

Cn =

6
6
6
6
4

C k Cn

k=0

h ni

n
X

C0 = 1, Cn+1 =

where & is the C bitwise and operator.


n no
2

=2

1;

mod 2 =

n=0
n 6= 0
nn
k

8
<0,
:1,

n no
1

n no
n

n n 1o
1o
+k
1
k
(n

k)&

otherwise

n n o
n
=
;
n 1
2

n no
k

1
2

=1

6= 0

k
1 X
k
( 1)
k! j=0

k
j

j ;

ACM ICPC Reference, page 7

University of So Paulo

Bell Numbers

Partition (number theory)

Bn is the number of equivalence relations on an n-set or, alternatively, the number of partitions of an n-set. It holds
that:

A partition of a positive integer n, is a way of writing n as a sum of positive integers. Two sums that dier only in
the order of their summands are considered to be the same partition. The number of partitions of n is given by the
partition function p(n). Ex: p(4) = 5 => {1+1+1+1} , {1+1+2} , {1+3} , {2+2} , {4}.

Bn =

n n o
X
n

k=0

Bn+1 =

n
X
n

k=0

Bn+p Bn + Bn+1

Bk ;

Bn =

1
1 X kn
;
e k=0 k!

(mod p)

(starting with B0 ): 1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, 4213597, 27644437, 190899322,
1382958545, 10480142147, 82864869804, 682076806159, 5832742205057, 51724158235372, 474869816156751,
4506715738447323, 44152005855084346, 445958869294805289, 4638590332229999353, ...

Narayana Numbers
N (n, k), n = 1, 2, 3..., 1 k n, is the number of expressions containing n pairs of parentheses which are correctly
matched and which contain k distinct nestings. For instance, N(4, 2) = 6 as with four pairs of parentheses six
sequences can be created which each contain two times the sub-pattern (): ()((())) (())(()) (()(())) ((()()))
((())()) ((()))().

The number of partitions of n in which the greatest part is m is equal to the number of partitions of n into m
parts.
The number of partitions of n in which all parts are 1 or 2 (or, equivalently, the number of partitions of n into
1 or 2 parts) is b n
2 + 1c.
(starting with p(0) = 1): 1, 1, 2, 3, 5, 7, 11, 15, 22, 30, 42, 56, 77, 101, 135, 176, 231, 297, 385, 490, 627...
P
p
k(3k 1)
k 1
Summation to calculate p(n) for the first n elements in O(n n) time. p(n) =
p(n
),
k ( 1)
2
where the summation is over all nonzero integers k (positive and negative) and p(m) is taken to be 0 if m < 0.
p(5k + 4) 0 (mod 5)
p(7k + 5) 0 (mod 7)
p(11k + 6) 0 (mod 11)
p(113 .13.k + 237) 0 (mod 13)

N (n, k) = 0, if k > n

Derangement (Desarranjo)

N (n, 1) = N (n, n) = 1

A derangement is a permutation of the elements of a set such that none of the elements appear in their original
position.
Suppose that there are n persons numbered 1, 2, . . . , n. Let there be n hats also numbered 1, 2, . . . , n. We have
to find the number of ways in which no one gets the hat having same number as his/her number. Let us assume
that first person takes the hat i. There are n 1 ways for the first person to choose the number i. Now there are 2
options:

N (n, k) =

N (n, k) =

(n

1 n n
n k k 1

n(n 1)
N (n
k)(n k + 1)

1, k)

N (n, 1) + N (n, 2) + N (n, 3) + ... + N (n, n) = Cn (Catalan N umber)

The Twelvefold Way


Let A be a set of m balls and B be a set of n boxes. The following table provides methods to compute the number
of equivalent functions f : A ! B satisfying specific constraints.
Balls
Boxes
Any
Injective
Surjective
nmo
n!
m
6
6
n
n!
(n m)!
n
n n o
nmo
X
m
6

m6n
k
n
k=0
m
n
m 1
+ n 1

6
m
m
n 1
n
X

(*)
p(m, k)
(**)p(m, n)
m6n
k=0

(**) is a definition and both (*) and (**) are very hard to compute. So do not try to.

Person i takes the hat of 1. Now the problem reduces to n 2 persons and n 2 hats.
Person i does not take the hat 1. This case is equivalent to solving the problem with n 1 persons n 1 hats
(each of the remaining n 1 people has precisely 1 forbidden choice from among the remaining n 1 hats).
From this, the following relation is derived:
dn = (n

1) (dn

+ dn

2)

d1 = 0
d2 = 1
Starting with n = 0, the numbers of derangements of n are: 1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961,
14684570, 176214841, 2290792932.

ACM ICPC Reference, page 8

University of So Paulo

Geometry 2D

Point Structure
271c
c9c4
4c40
4c40
13ed
5753
0188
a930
4fac
9684
e00a
08fb
ed7d
a117
370c
92cf
cc80
1b1c
0db4
425f
fc93
ed60
30cd
bf2c
b780
9948
522c
ddfe

inline int cmp(double x, double y = 0, double tol = eps) {


return (x <= y + tol) ? (x + tol < y) ? -1 : 0 : 1;
}
struct point {
double x, y;
point(double x = 0, double y = 0): x(x), y(y) {}
point operator +(point q) { return point(x + q.x, y + q.y); }
point operator -(point q) { return point(x - q.x, y - q.y); }
point operator *(double t) { return point(x * t, y * t); }
point operator /(double t) { return point(x / t, y / t); }
double operator *(point q) {return x * q.x + y * q.y;}//a*b = |a||b|cos(ang)
double operator %(point q) {return x * q.y - y * q.x;}//a%b = |a||b|sin(ang)
double polar() { return ((y > -eps) ? atan2(y,x) : 2*Pi + atan2(y,x)); }
double mod() { return sqrt(x * x + y * y); }
double mod2() { return (x * x + y * y); }
point rotate(double t) {return point(x*cos(t)-y*sin(t), x*sin(t)+y*cos(t));}
int cmp(point q) const {
if (int t = ::cmp(x, q.x)) return t;
return ::cmp(y, q.y);
}
bool operator ==(point q) const { return cmp(q) == 0; }
bool operator !=(point q) const { return cmp(q) != 0; }
bool operator < (point q) const { return cmp(q) < 0; }
static point pivot;
};
point point::pivot;
typedef vector<point> polygon;

Auxiliary Functions
160a
ab7c
ab7c
27db
69a1
34b1
34b1
34b1
06d3
6a85
126a
126a
126a
126a
6c5c
bf72
bc40

double abs(point p) { return hypot(p.x, p.y); }


double arg(point p) { return atan2(p.y, p.x); }
inline int ccw(point p, point q, point r) {
return cmp((p - r) % (q - r));
}
//Projeta o vetor v sobre o vetor u (cuidado precisao)
point proj(point v, point u) {
return u*((u*v) / (u*u));
}
//\angle(p,q,r)| e o menor angulo entre os vetores u(p-q) e v(r-q)
// p->q->r virar pra esquerda => angle(p,q,r) < 0
inline double angle(point p, point q, point r) {
point u = p - q, v = r - q;
return atan2(u % v, u * v);

615a
615a
615a
a582
51cd
9480
9480
9480
cab9
0ee2
e529
9307
5a00
a282
e435
c388
b193
b193
b193
f311
3285
b348
3b09
d2b9
f5b7
ed51
ed51
ed51
ed51
ed51
cf13
5047
7f2c
6ea3
0935
8850
294c
8a8d
8a8d
8a8d
550d
d6fd
49b7
ae66
ae66
ae66
ae66
ae66
78f3
fe30
f7e8
23db
ccd3
549a
549a

}
//Decide se q esta sobre o segmento fechado pr.
bool between(point p, point q, point r) {
return ccw(p, q, r) == 0 && cmp((p - q) * (r - q)) <= 0;
}
//Decide se os segmentos fechados pq e rs tem pontos em comum
bool seg_intersect(point p, point q, point r, point s) {
point A = q - p, B = s - r, C = r - p, D = s - q;
int a = cmp(A % C) + 2 * cmp(A % D);
int b = cmp(B % C) + 2 * cmp(B % D);
if (a == 3 || a == -3 || b == 3 || b == -3) return false;
if (a || b || p == r || p == s || q == r || q == s) return true;
int t = (p < r) + (p < s) + (q < r) + (q < s);
return t != 0 && t != 4;
}
// Calcula a distancia do ponto r ao segmento pq.
double seg_distance(point p, point q, point r) {
point A = r - q, B = r - p, C = q - p;
double a = A * A, b = B * B, c = C * C;
if (cmp(b, a + c) >= 0) return sqrt(a);
else if (cmp(a, b + c) >= 0) return sqrt(b);
else return fabs(A % B) / sqrt(c);
}
// Classifica o ponto p em relacao ao poligono T.
// Retorna 0, -1 ou 1 dependendo se p esta no exterior, na fronteira
// ou no interior de T, respectivamente.
int in_poly(point p, polygon& T) {
double a = 0; int N = T.size();
for (int i = 0; i < N; i++) {
if (between(T[i], p, T[(i+1) % N])) return -1;
a += angle(T[i], p, T[(i+1) % N]);
}
return cmp(a) != 0;
}
//Encontra o ponto de intersecao das retas pq e
point line_intersect(point p, point q, point r,
point a = q - p, b = s - r, c = point(p % q,
return point(point(a.x, b.x) % c, point(a.y,
}

rs.
point s) {
r % s);
b.y) % c) / (a % b);

// Calcula a area orientada do poligono T.


// Se o poligono P estiver em setido anti-horario, poly_area(P) > 0,
// e <0 caso contrario
double poly_area(polygon& T) {
double s = 0; int n = T.size();
for (int i = 0; i < n; i++)
s += T[i] % T[(i+1) % n];
return s / 2;
}

ACM ICPC Reference, page 9

University of So Paulo

549a
585a
f167
3b2d
7752
7752
7752
3df1
e7c6
9823
6227
308e
5bd2
48e2
bbb9
efc0

//Calcula o incentro de um triangulo


point incenter(point p, point q, point r) {
double a = (p-q).mod(), b = (p-r).mod(), c = (q-r).mod();
return (r*a + q*b + p*c) / (a + b + c);
}
//Centro de massa de um poligono
point centro_massa(polygon p) {
double x=0., y=0., area = poly_area(p);
p.push_back(p[0]);
for (int i = 0; i < p.size()-1; i++) {
x += (p[i].x + p[i+1].x) * (p[i] % p[i+1]);
y += (p[i].y + p[i+1].y) * (p[i] % p[i+1]);
}
return point(x/(6*area), y/(6*area));
}

Convex Hull
d41d
d41d
d41d
f7bf
1cb2
69c0
f7e9
ea84
119c
119c
119c
119c
5b79
548d
76fb
bfee
4a7a
6a93
6a93
b5fc
b5fc
a64e
426e
bd98
df01
519d
e39f

// Comparacao radial.
// Obs: suponha tds pontos no vetor p[] = p[]-pivot, (pivot = min_elemento(p))
// tds ptos do novo p[] estarao no 1 e 4 quadrante ordenado no sentido anti-hor
bool radial_lt(point p, point q) {
point P = p - point::pivot, Q = q - point::pivot;
double R = P % Q;
if (cmp(R)) return R > 0;
return cmp(P * P, Q * Q) < 0;
}
// Determina o fecho convexo de um conjunto de pontos no plano.
// Destroi a lista de pontos T.
polygon convex_hull(vector<point>& T) {
int j = 0, k, n = T.size(); polygon U(n);
point::pivot = *min_element(all(T));
sort(all(T), radial_lt);
for (k = n-2; k >= 0 && ccw(T[0], T[n-1], T[k]) == 0; k--);
reverse((k+1) + all(T));
for (int i = 0; i < n; i++) {
// troque o >= por > para manter pontos colineares
while (j > 1 && ccw(U[j-1], U[j-2], T[i]) >= 0) j--;
U[j++] = T[i];
}
U.erase(j + all(U));
return U;

Convex Polygon Intersection


d41d
d41d
32b5
e0a6
8d65
1f0c
2546
377b
261f
43f8
240f
22de
7f4b
1839
52b9
4868
ff0c
2afe
816a
d2e3
5766
83e3
95ef
440c
68f7
8d2f
2740
74ba
2fa0
1d34
1d34
09a0
c759
c27d
8d7f
913d
9a7e
993f
35c1
41e9
113c

// Determina o poligono intersecao dos dois poligonos convexos P e Q.


// Tanto P quanto Q devem estar orientados positivamente.(anti-horario)
polygon poly_intersect(polygon& P, polygon& Q) {
int m = Q.size(), n = P.size();
int a = 0, b = 0, aa = 0, ba = 0, inflag = 0;
polygon R;
while ((aa < n || ba < m) && aa < 2*n && ba < 2*m) {
point p1 = P[a], p2 = P[(a+1) % n], q1 = Q[b], q2 = Q[(b+1) % m];
point A = p2 - p1, B = q2 - q1;
int cross = cmp(A % B), ha = ccw(p2, q2, p1), hb = ccw(q2, p2, q1);
if (cross == 0 && ccw(p1, q1, p2) == 0 && cmp(A * B) < 0) {
if (between(p1, q1, p2)) R.push_back(q1);
if (between(p1, q2, p2)) R.push_back(q2);
if (between(q1, p1, q2)) R.push_back(p1);
if (between(q1, p2, q2)) R.push_back(p2);
if (R.size() < 2) return polygon();
inflag = 1; break;
} else if (cross != 0 && seg_intersect(p1, p2, q1, q2)) {
if (inflag == 0) aa = ba = 0;
R.push_back(line_intersect(p1, p2, q1, q2));
inflag = (hb > 0) ? 1 : -1;
}
if (cross == 0 && hb < 0 && ha < 0) return R;
bool t = cross == 0 && hb == 0 && ha == 0;
if (t ? (inflag == 1) : (cross >= 0) ? (ha <= 0) : (hb > 0)) {
if (inflag == -1) R.push_back(q2);
ba++; b++; b %= m;
} else {
if (inflag == 1) R.push_back(p2);
aa++; a++; a %= n;
}
}
if (inflag == 0) {
if (in_poly(P[0], Q)) return P;
if (in_poly(Q[0], P)) return Q;
}
R.erase(unique(all(R)), R.end());
if (R.size() > 1 && R.front() == R.back()) R.pop_back();
return R;
}

Polygon-Line Intersection

}
d41d
d41d
d41d
abcb
c8be
5ec6

//retorna tds trechos da reta que passa por s(s.a != s.b) coberta
//por p(simple polygon)
//tempo:O(n log n), memoria: O(n), onde n = p.size() TODO testar
vector <segment> cobertura(segment s, polygon p) {
if (cmp(poly_area(p)) < 0) reverse(all(p)); //p deve esta no sentido anti-hr
int n = (int)p.size();

ACM ICPC Reference, page 10

University of So Paulo

5ec6
ed2a
a951
592f
a782
73c9
3fc2
3fc2
3630
3630
14b9
aab9
02c0
82d2
6957
e155
84d6
c42e
d4d8
50e6
50e6
fa88
6c84 }

polygon q;
p.pb(p[0]), p.pb(p[1]), p.pb(p[2]);
for (int i = 1; i <= n; i++) {
point u = p[i], v = p[i+1];
int d0 = ccw(s.a,s.b,p[i-1]), d1 = ccw(s.a,s.b,p[i]);
int d2 = ccw(s.a,s.b,p[i+1]), d3 = ccw(s.a,s.b,p[i+2]);
if (d1 == d2) continue;
if (d1 * d2 == -1)
q.pb(line_intersect(s.a, s.b, u, v));
else if (d1 == 0 && (d0*d2 == -1 || ccw(p[i-1], p[i], p[i+1]) > 0))
q.pb(line_intersect(s.a, s.b, u, v));
else if (d2 == 0 && ccw(p[i], p[i+1], p[i+2]) > 0 && d1*d3 >= 0)
q.pb(line_intersect(s.a, s.b, u, v));
}
sort(all(q));
vector <segment> seg;
for (int i = 0; i < q.size(); i += 2) seg.pb( segment(q[i], q[i+1]));
return seg;

Polygon Triangulation
395e
80e5
80e5
80e5
eef9
9db8
c0f0
a8dc
a8dc
5a7a
038b
2b13
1567
c9eb
b43f
4cf0
cac8
b1e3
b1e3
b1e3
e82d
aea2
2911
2911
9b58
e616

#define N_VERTEX 10000


int orelha[N_VERTEX], prox[N_VERTEX], prev[N_VERTEX];
// verifica se p[prev[id]~p[id]~p[prox[id]] forma uma orelha p
bool eh_orelha(polygon &p, int id) {
int n = p.size();
point a = p[prev[id]], b = p[prox[id]];
if (ccw(a, p[id], b) <= 0) return false;
for (int i = 0; i < n; i++) {
int j = ((i+1<n)?(i+1):(i+1-n)); //j = (i+1)%n
if (i == prev[id] || i == prox[id] ||
j == prev[id] || j == prox[id]) continue;
if (seg_intersect(p[i], p[j], a, b))
return false;
}
return true;
}
//Complexidade O(n^2)
//assume q o poligono eh simples com 3 ou mais vertices, sem pontos repitidos
void triangulacao(polygon &p) {
int n = p.size(), id = 0;
if (cmp(poly_area(p)) < 0) reverse(all(p)); //deixa p no sentido anti-hor
for (int i = 0; i < n; i++) {
prev[i] = ((i==0)?(n-1):(i-1));

fd13
fd13
aa38
0401
08d2
229e
229e
229e
229e
05eb
05eb
0bed
41b5
e844
a6df
85d8
c9f0
37ca
2202
2202
b944
7fe3 }

prox[i] = ((i+1<n)?(i+1):(i+1-n));
orelha[i] = eh_orelha(p, i);
}
while (n > 3) {
while (!orelha[id]) id = prox[id];
//triangulo p[id], p[prev[id]], p[prox[id]]
//diagonal inserida => prev[id] <-> prox[id]
printf("%2d %2d %2d\n", id, prox[id], prev[id]);
int ant = prev[id], next = prox[id];
prox[ant] = next;
prev[next] = ant;
orelha[ant] = eh_orelha(p, ant);
orelha[next] = eh_orelha(p, next);
n--;
id = prox[id];
}
//triangulo p[id], p[prox[id]], p[prox[prox[id]]]
printf("%2d %2d %2d\n", id, prox[id], prox[prox[id]]);

Closest Pair
904d
35c2
1db4
6b34
6b34
c8e3
4705
6f5b
6f5b
6f5b
31d9
37f0
dfc0
dfc0
6568
f57e
a0d9
264f
8b4b
4faa
323f
1eb9
6fb0
c40a
c40a
f209
5430

#define inf 1e20


#define N_PTS 300010
#define LOG_PTS 25
point X[N_PTS], Y[N_PTS], Yrl[LOG_PTS][N_PTS];
inline bool cmpy(const point &a, const point &b) {
return (cmp(a.y,b.y) < 0 || (cmp(a.y,b.y) == 0 && cmp(a.x,b.x) < 0));
}
//Retorna o quadrado da menor distancia
inline double divide_conquer(int n, int cont, point X[], point Y[]) {
if (n <= 1) return inf;
if (n == 2) return (X[0]-X[1]).mod2();
int left = n/2; int right = n-left;
int l = 0, r = left;
point mid = (X[left-1] + X[left])/2;
for (int i = 0; i < n; i++) {
if (Y[i] < mid) Yrl[cont][l++] = Y[i];
else Yrl[cont][r++] = Y[i];
}
double resp = inf;
resp = min(resp, divide_conquer(left, cont+1, X, Yrl[cont]));
resp = min(resp, divide_conquer(right, cont+1, X+left, Yrl[cont]+left));
for (int i = 0; i < n; i++) {
if (cmp(abs(Y[i].x-mid.x), resp) > 0) continue;

ACM ICPC Reference, page 11

University of So Paulo

6e13
for (int j = max(0, i-8); j < i; j++)
bad4
resp = min(resp, (Y[i]-Y[j]).mod2());
3bfb
}
0ccc
return resp;
9b71 }
9b71
9b71
ce21 double closest_pair(vector <point> &p) {
cb73
for (int i = p.size()-1; i >= 0; i--) X[i] = Y[i] = p[i];
88d6
sort(X, X+p.size());
fffe
sort(Y, Y+p.size(), cmpy);
3ad4
return sqrt(divide_conquer(p.size(), 0, &X[0], &Y[0]));
9554 }

Crosses Half-Plane
d41d
d41d
d41d
d41d
3755
c316
3b60
3b60
3b60
4981
f194
9a0e
88e0
7689
9df1
1d83
c519
1645
9943

// Retorna a interseccao de um poligono simples com um semiplano


// TODO cuidado qdo o poligono nao for convexo
// sumpoem q o semiplano eh o lado esquerdo, indo de p1 para p2
// p pode estar em qlqr direcao( poligono de retorno esta no msm sentido que p)
polygon halfplane(polygon& p, line& semiplano) {
polygon q;
point p1 = semiplano.first, p2 = semiplano.second;
// Sequencia poligono convexo exaustiva, para determinar se o semiplano.
int n = p.size();
for (int i = 0; i < n; i++) {
double c = (p2-p1) % (p[i]-p1);
double d = (p2-p1) % (p[(i+1)%n]-p1);
if (cmp(c) >= 0) q.push_back(p[i]);
if (cmp(c * d) < 0)
q.push_back(line_intersect(p1, p2, p[i], p[(i+1)%n]));
}
return q;
}

N segments Intersection
67e3
0bfd
dfe5
fb83
72c2
7e34
08e1
5f79
8abb
8abb
fd2a
a86d

typedef ll ptype;
struct segment {
point a, b;
segment(point a=point(0,0), point b=point(0,0)): a(a), b(b) {}
double interpolate(ptype x) {
if (a.x == b.x) return min(a.y, b.y);
return a.y + (double)(b.y - a.y) / (b.x - a.x) * (x - a.x);
}
};
struct event {
ptype x;

f8b1
56d0
d428
0551
5ae4
c7e3
c7e3
60c0
dc88
c5a6
bc5e
1a89
276a
e3c1
49a9
ab9c
ab9c
083a
8737
e3b4
1985
1985
4fcf
fee1
12fd
12fd
6be6
7136
f399
9c01
b204
f7e9
4839
f1b8
bec0
bec0
3058
66a2
d61e
323b
323b
38f1
cf62
08b9
68c6
ae7e
a7da
15b5
c496
9bf4
2465
af6f
db87
3472
07d6

int tp, id;


event(ptype x=0, int tp=0, int id=0): x(x), tp(tp), id(id) {}
bool operator<(const event &e) const {
return x < e.x || (x == e.x && tp > e.tp);
}
};
vector<segment> T;
struct CMP {
static ptype x;
bool operator()(const int &i, const int &j) {
return T[i].interpolate(x) < T[j].interpolate(x) - eps;
}
};
ptype CMP::x = 0;
set<int, CMP> S;
#define auto set<int>::iterator
auto prev(auto it) {return it == S.begin() ? S.end() : --it;}
auto next(auto it) {return it == S.end() ? S.end() : ++it;}
bool null(auto it) {return it == S.end();}
bool intersect(const int &i, const int &j) {
return seg_intersect(T[i].a, T[i].b, T[j].a, T[j].b);
}
pii segment_intersect (const vector<segment> &p) {
T = p;
int n = (int) T.size();
vector<event> e;
f(i, 0, n) {
e.push_back (event (min (T[i].a.x, T[i].b.x), +1, i));
e.push_back (event (max (T[i].a.x, T[i].b.x), -1, i));
}
sort(all(e));
S.clear();
f(i, 0, e.size()) {
CMP::x = e[i].x;
int& id = e[i].id;
if (e[i].tp == +1) { // insert segment
auto nid = S.lower_bound(id);
auto pid = prev(nid);
if (!null(nid) && intersect(*nid, id)) return mp((*nid), id);
if (!null(pid) && intersect(*pid, id)) return mp((*pid), id);
S.insert(nid, id);
}
else { // remove segment
auto cid = S.lower_bound(id);
auto pid = prev(cid), nid = next(cid);
if (!null(pid) && !null(nid) && intersect(*pid, *nid))
return mp((*pid), (*nid));
S.erase(cid);
}

ACM ICPC Reference, page 12

University of So Paulo

c2b5
85a3
5edd }

ff4a
80cd
fe16
2b8c
081c
d825
88a4
Circle Structure
88a4
4d74
aa81 struct circle {
7e41
5235
point c; double r;
8b21
0ba6
circle(point c = point(0,0), double r=0.0):c(c), r(r) {}
8b21
639a
bool inside(point &e) { return cmp((e-c).mod(), r) <= 0; }
ae3c
9757 };
ae3c
a1cf
8514
9d66
1354
Circle Intersection
dbe0
607c
d41d //assume que ha pelo menos 1 ponto de interseccao
b7d1
d41d //cuidado com circulos iguais, sem intersecao (um dentro do outro)
7470
9b67 pair<point, point> interseccao(circle a, circle b) {
0581
4979
if (cmp(a.r, b.r) < 0) swap(a, b);
029f
99d7
double R = a.r, r = b.r, d = (b.c-a.c).mod();
029f
ee39
double x1 = (R*R - r*r + d*d) / (2*d);
35e2
9881
double h = 0.0;
59b4
f8cf
if (cmp(R*R - x1*x1) > 0) h = sqrt(R*R - x1*x1);
59b4
2cb8
point v = ((b.c-a.c)/d) * R;
3298
48ac
return mp(a.c + v.rotate(h/R, x1/R), a.c + v.rotate(-h/R, x1/R));
4514
ee26 }
4514
65d8
f064
64e4
Circle Union
7453
d4d3
f244 void increment(double ini, double fim, double &Area, double &Perim, circle &q) { a2ca
a489
5456
double teta = (cmp(fim,ini)>=0) ? (2*Pi-fim+ini) : (ini-fim);
7592
7959
Perim += teta * q.r;
13e7
6dde
Area += 0.5*teta*quad(q.r) - 0.5*sin(teta)*quad(q.r);
74ac
f25f
point a = (point(cos(fim), sin(fim)) * q.r) + q.c;
bf78
557d
point b = (point(cos(ini), sin(ini)) * q.r) + q.c;
240b
7f51
Area += 0.5*(a % b);
2bf4
e7cf }
6d26
e7cf //Calcula a area e o perimetro em O(n^2*logn)
accc
e7cf //Consome memoria O(n)
4654
b0a6 double area_uniao_circle(vector <circle> &T) {
79eb
f354
vector <circle> p;
8c91
ee7b
vector < pair<double, double> > seg;
dfa2
554f
point e, a, b;
b486
2ff7
double Area = 0, Perim = 0, teta, ini, fim;
6444
2ff7
2ff7
//remove circles repitidos, com area nula, ou circle dentro de outro circle 8849
08f5 }
c3ee
f(i, 0, T.size()) {
2fcf
bool check = cmp(T[i].r) > 0;

for (int j = 0; j < T.size() && check; j++) {


if (T[i]==T[j]) check = (i>=j);
else if (cmp((T[i].c-T[j].c).mod()+T[i].r, T[j].r) <= 0)
check = false;
}
if (check) p.pb(T[i]);

}
return mp(-1,-1);

}
for (int i = 0; i < p.size(); i++) {
seg.clear();
for (int j = 0; j < p.size(); j++) if (i != j) {
//p[i] e p[j] nao tem 2 pontos em comum
if ((p[i].c-p[j].c).mod() > p[i].r + p[j].r -eps) continue;
pair <point, point> inter = interseccao2(p[i], p[j]);
teta = angle(inter.first, p[i].c, inter.second);
if (teta > eps) {
e = (inter.first - p[i].c).rotate(teta/2) + p[i].c;
if (p[j].inside(e) == false) swap( inter.first, inter.second);
}
else {
e = (inter.first - p[i].c).rotate((2*Pi+teta)/2) + p[i].c;
if (p[j].inside(e) == false) swap( inter.first, inter.second);
}
ini = (inter.first - p[i].c).polar();
fim = (inter.second - p[i].c).polar();
a = (point(cos(ini), sin(ini)) * p[i].r) + p[i].c;
b = (point(cos(fim), sin(fim)) * p[i].r) + p[i].c;
if (ini > fim) {
seg.pb( mp(ini, 2*Pi));
seg.pb( mp(0, fim));
}
else seg.pb( mp(ini, fim));
}
sort(all(seg));
if ((int) seg.size() == 0) {
Perim += 2*Pi*p[i].r;
Area += Pi*quad(p[i].r);
continue;
}
fim = seg[0].second;
for (int j = 1; j < seg.size(); j++) {
if (cmp(fim, seg[j].first) < 0) {
increment(seg[j].first, fim, Area, Perim, p[i]);
}
fim = max(fim, seg[j].second);
}
increment(seg[0].first, fim, Area, Perim, p[i]);
}
return Area;

ACM ICPC Reference, page 13

University of So Paulo

6b33
bd68 }

return fabs(ans);

Minimum Spanning Circle


d41d
22e1
3732
0f79
0250
0250
c95d
7645
018e
cc09
a542
e1c1
335f
069f
5c05
6abf
a55e
9d60
50bc
a82f
09a6
49db

//Calcula o circuncentro de um triangulo


point circumcenter(point p, point q, point r) {
point a = p-r, b = q-r, c = point(a*(p + r) / 2, b*(q + r) / 2);
return point(c % point(a.y, b.y), point(a.x, b.x) % c) / (a % b);
}
circle spanning_circle(vector<point>& T) {
int n = T.size();
random_shuffle(all(T));
circle C(point(), -INFINITY);
for (int i = 0; i < n; i++) if (!C.inside(T[i])) {
C = circle(T[i], 0);
for (int j = 0; j < i; j++) if (!C.inside(T[j])) {
C = circle((T[i] + T[j]) / 2, abs(T[i] - T[j]) / 2);
for (int k = 0; k < j; k++) if (!C.inside(T[k])) {
point o = circumcenter(T[i], T[j], T[k]);
C = circle(o, abs(o - T[k]));
}
}
}
return C;
}

Circle-Polygon Intersection
d41d
6673
6421
91ca
a8b9
a8b9
3da3
eadd
ffb6
726d
6c18
6c18
5fcf
18c2
7c63
7c63
7c63
64ab
643c
2a56
65d0
ef35

//area da intersecao de um triangulo a,b,S.c com circulo S


double area(point a, point b, circle S) {
double aa=(S.c-a).mod(), bb=(S.c-b).mod(), cc=seg_distance(a, b, S.c);
if (cmp(aa,S.r) <= 0 && cmp(bb,S.r) <= 0) return 0.5*fabs((a-S.c)%(b-S.c));
if (cmp(cc,S.r) >= 0) return 0.5*fabs(S.r * S.r * angle(a, S.c, b));
if (cmp(aa, bb) > 0) {swap(a, b); swap(aa,bb); }
double A=(a-b).mod2(), B=2*((a-b)*(b-S.c)), C=(b-S.c).mod2()-S.r*S.r;
double t = ((cmp(B*B-4*A*C)==0)?0.0: sqrt(B*B-4*A*C));
double x1 = 0.5*(-B-t)/A, x2 = 0.5*(-B+t)/A;
point p1 = a*x1 + b*(1-x1), p2 = a*x2 + b*(1-x2);
if (cmp(aa, S.r) < 0) return area(a, p1, S) + area(p1, b, S);
return area(a, p2, S) + area(p2, p1, S) + area(p1, b, S);
}
//area da intersecao de poligono(simples qlqr) com circulo S O(n)
double area(polygon &T, circle S) {
double ans=0.0;
int n = (int)T.size();
for (int i = 0; i < n; i++)
ans += (area(T[i], T[(i+1)%n], S) * ccw(T[i], T[(i+1)%n], S.c));

Geometry 2D - Integer

Geometry Integer
bd39
5fd8
4e39
15ac
d57a
d57a
d57a
ee01
3992
e388
2acd
5180
4842
4842
4842
4842
4842
4842
4842
8390
2696
17f8
3065
6ba3
786a
198d
38bc
78eb
a580
a580
a580
a580
a580
a580
a580
a580
a580
a580
a580
ebb2
18f8
c585
c585
0d3d
0d3d

bool seg_intersect1d (ll


if (l1 > r1) swap(l1,
if (l2 > r2) swap(l2,
return max(l1, l2) <=
}

l1, ll r1, ll l2, ll r2) {


r1);
r2);
min(r1, r2);

//Decide se os segmentos fechados pq e rs tem pontos em comum


bool seg_intersect(point p, point q, point r, point s) {
return seg_intersect1d(p.x, q.x, r.x, s.x)
&& seg_intersect1d(p.y, q.y, r.y, s.y)
&& ccw(p, q, r) * ccw(p, q, s) <= 0
&& ccw(r, s, p) * ccw(r, s, q) <= 0;
}
//////////////////////////////////////////////////////////////////////////////
// Classifica o ponto p em relacao ao poligono T.
//
// Retorna 0, -1 ou 1 dependendo se p esta no exterior, na fronteira
// ou no interior de T, respectivamente.
int in_poly(point p, polygon& T) {
int n = T.size(), cnt = 0;
for (int i = 0, j = n-1; i < n; j = i++) {
if (between(T[i], p, T[j])) return -1;
if ((T[i].y > p.y) != (T[j].y > p.y)) {
cnt ^= (ccw(p, T[j], T[i])*(T[j].y-T[i].y) > 0);
}
}
return cnt;
}

//TESTAR XXX
//////////////////////////////////////////////////////////////////////////////
// Returns a list of points on the convex hull in counter-clockwise order.
// Note: the last point in the returned list is the same as the first one.
// Se T.size()==1 => H.size()==1
//trocar ccw(H[k-1], T[i], H[k-2]) <= 0 por ccw(...) < 0,
//para incluir pts colineares
// Monotone hull O(nlogn)
polygon convex_hull(vector<point> T) {
int n = T.size(), k = 0;
polygon H(2*n);
sort(T.begin(), T.end());
// Build lower hull

ACM ICPC Reference, page 14

University of So Paulo

8045
50b0
8c5e
608e
608e
0201
1007
b5d8
9df1
94cb
7a34
2e5b }

for (int i = 0; i < n; i++) {


while (k >= 2 && ccw(H[k-1], T[i], H[k-2]) <= 0) k--;
H[k++] = T[i];
}
// Build upper hull
for (int i = n-2, t = k+1; i >= 0; i--) {
while (k >= t && ccw(H[k-1], T[i], H[k-2]) <= 0) k--;
H[k++] = T[i];
}
H.resize(k);
return H;

e08c
d6d7
4b8c
4b8c
4b8c
7880
44f8
b5fd
4442
6e35
479c
2e96
bc3c
79a8
3de6
de90
7 Geometry 3D
df01
7581
Geometry 3D
b6cc
3bfe
b44d
a616 #define vetor point
af47
a616
f643
a616 // FORMULAS.
6b62
a616 // vetores a,b; a*b = a.mod()*b.mod()*cos( angulo entre a e b) =>
6b62
a616 // a*b = |a|*|b|*cos(t)
6b62
a616 // vetores a,b; (a^b).mod() = a.mod()*b.mod()*sin( angulo entre a e b)
1780
a616
f9f6
45c8 inline int cmp(ld x, ld y = 0, ld tol = eps) {
1f9f
2939
return (x <= y + tol) ? (x + tol < y) ? -1 : 0 : 1;
2b63
426f }
2b63
858c struct point {
2b63
148a
ld x, y, z;
1ba8
a276
point(ld x = 0, ld y = 0, ld z = 0): x(x), y(y), z(z) {}
ef7a
78a6
point operator +(point q) { return point(x + q.x, y + q.y, z + q.z); }
dc8e
d092
point operator -(point q) { return point(x - q.x, y - q.y, z - q.z); }
f81e
55b5
point operator *(ld t) { return point(x * t, y * t, z * t); }
6d1e
0646
point operator /(ld t) { return point(x / t, y / t, z / t); }
0366
0286
point operator ^(point q) {
1ea3
b5e0
return point(y*q.z - z*q.y, z*q.x - x*q.z, x*q.y - y*q.x); }
1ea3
10a6
ld operator *(point q) { return x * q.x + y * q.y + z * q.z; }
1ea3
44b7
ld mod() { return sqrt(x * x + y * y + z * z); }
a2a0
8344
ld mod2() { return x * x + y * y + z * z; }
feaf
point projecao(vetor u) { return (*this) * ((*this)*u) / ((*this)*(*this)); } 56b2
8db1
feaf
8db1
5eb8
int cmp(point q) const {
059b
ff5c
if (int t = ::cmp(x, q.x)) return t;
e035
82ce
if (int t = ::cmp(y, q.y)) return t;
11d5
d86a
return ::cmp(z, q.z);
11d5
940d
}
11d5
9b26
bool operator ==(point q) const { return cmp(q) == 0; }
4985
b245
bool operator !=(point q) const { return cmp(q) != 0; }
ee85
ce46
bool operator < (point q) const { return cmp(q) < 0; }
2f7c
bb0f };
4a60
bb0f
8dea
bb0f // RETAS, SEMIRETAS, SEGMENTOS E TRIANGULOS

struct reta {
point a, b;// <--a---b--->
reta(point A=point(0,0,0), point B=point(0,0,0)): a(A), b(B) { }
//verifica se o ponto p esta na reta ab
bool belongs(point p) {
return cmp(((a-p)^(b-p)).mod()) == 0;
}
};
struct semireta {
point a, b; // |a---b--->
semireta(point A=point(0,0,0), point B=point(0,0,0)): a(A), b(B) { }
};
struct segmento {
point a, b; // |a---b|
segmento(point A=point(0,0,0), point B=point(0,0,0)): a(A), b(B) { }
bool between(point p) {
return cmp(((a-p)^(b-p)).mod()) == 0 && cmp((a-p) * (b-p)) <= 0;
}
};
struct triangulo {
point a, b, c;
triangulo(point A, point B, point C): a(A), b(B), c(C) { }
ld area() { return 0.5*((b-a)^(c-a)).mod(); }
//retorna o ponto que eh a projecao de p no plano abc
point projecao(point p) {
vetor w = (b-a)^(c-a);
return p - w.projecao(p-a);
}
//verifica se p esta dentro de abc
// se retornar true, entao a,b,c,p sao coplanares
bool inside(point p) {
return cmp(((p-a)^(b-a)).mod() +
((p-b)^(c-b)).mod() +
((p-c)^(a-c)).mod() ((b-a)^(c-a)).mod()) == 0;
}
};
//Produto misto
ld produto_misto(point p, point q, point r) {
return (p^q)*r;
}
//Volume do tetraedro pqrs
ld volume(point p, point q, point r, point s) {
return fabs(produto_misto(q-p, r-p, s-p)) / 6.0;
}
// DISTANCIA ENTRE OBJETOS GEOMETRICOS
ld distancia(point p, reta r) {
vetor v = r.b-r.a, w = p-r.a;
return (v^w).mod() / v.mod();
}
ld distancia(point p, semireta s) {

ACM ICPC Reference, page 15

University of So Paulo

3c72
341c
b99b
1027
cdef
7700
cb69
8d5f
ad83
55c4
1268
a756
c71d
0e8c
c3f9
cf4b
4622
3f36
65cd
4b58
4a12
23fb
6ee7
b72c
cce1
bd44
9c8d
5d82
d414
4733
f55a
8eae
e75f
397b
0da3
4849
1f96
9028
cf88
6402
185c
b645
4231
ff9e
39c6
78e4
5fdb
320d
320d
320d
fd93
6645
c16b
39fe
39fe

vetor v = s.b-s.a, w = p-s.a;


if (cmp(v*w) <= 0) return (p-s.a).mod();
return (v^w).mod() / v.mod();
}
ld distancia(point p, segmento s) {
point proj = s.a + (s.b-s.a).projecao(p-s.a);
if (segmento(s.a,s.b).between(proj))
return (p-proj).mod();
return min((p-s.a).mod(), (p-s.b).mod());
}
ld distancia(point p, triangulo T) {
point proj = T.projecao(p);
if (T.inside(proj)) return (p-proj).mod();
return min(
distancia(p, segmento(T.a, T.b)),
min(distancia(p, segmento(T.b, T.c)),
distancia(p, segmento(T.c, T.a))));
}
ld distancia(reta r, reta s) {
vetor u = r.b-r.a, v = s.b-s.a, w = s.a-r.a;
ld a = u*u, b = u*v, c = v*v, d = u*w, e = v*w;
ld D = a*c - b*b, sc, tc;
if (D < eps) {
sc = 0;
tc = (b > c) ? d/b : e/c;
} else {
sc = (b*e - c*d) / D;
tc = (a*e - b*d) / D;
}
vetor dP = w + (u * sc) - (v * tc);
return dP.mod();
}
ld distancia(segmento X, segmento Y) {
point p = X.a, q = X.b;
point r = Y.a, s = Y.b;
if (p == q) return distancia(p, Y);
if (r == s) return distancia(r, X);
if (cmp(((p-q)^(s-r)).mod()) == 0)
return min( min(distancia(p,Y),distancia(q,Y)),
min(distancia(p,Y),distancia(q,Y)));
vetor v = q-p, u = s-r, t = (r-p);
ld b = ((t*v)*(v*u) - (t*u)*(v*v)) / ((u*u)*(v*v) - (u*v)*(v*u));
ld a = (b*(u*v) + t*v) / (v*v);
if (cmp(a) >= 0 && cmp(a,1.0) <= 0 && cmp(b) >= 0 && cmp(b,1.0) <= 0)
return ((p+v*a) - (r+u*b)).mod();
point ini = ((cmp(a) < 0)?p:q);
point fim = ((cmp(b) < 0)?r:s);
return (ini-fim).mod();
}
//Calcula o centro da esfera circunscrita de uma piramide triangular
point circumsphere(point p, point q, point r, point s) {
point a = q-p, b = r-p, c = s-p;
return p + ((a^b)*c.mod2() + (c^a)*b.mod2() + (b^c)*a.mod2()) / (a*(b^c)*2);
}

39fe
c9a7
1653
7118
a779
05bf
26be
e1e1
d5fe
4a16
fc14
9023
9023
9023
9023
1da8
4015
9d39
814e
1e07
89c3
b08d
3002
9d7d

//Calcula o circuncentro de um triangulo no espaco


point circumcenter(point p, point q, point r) {
point a = (q-p)^((q-p)^(r-p)), b = (r-p)^((q-p)^(r-p)); ld t;
if (fabs(a.x) < eps) t = (r.x-q.x)/2/b.x;
else if (fabs(a.y) < eps) t = (r.y-q.y)/2/b.y;
else if (fabs(a.z) < eps) t = (r.z-q.z)/2/b.z;
else {
t = a.x*(r.y-q.y) - a.y*(r.x-q.x);
t = t / (2*a.y*b.x - 2*a.x*b.y);
}
return (p+q)/2 + a*t;
}
//Verifica se T[a], T[b], T[c] eh face do convex hull
//OBS.: Cuidade com mais de 3 pontos coplanares
bool ishullface(vector <point> &T, int a, int b, int c) {//TODO testar
int n = (int)T.size(), pos = 0, neg = 0;
for (int i = 0; i < n; i++) {
ld pm = produto_misto(T[b]-T[a], T[c]-T[a], T[i]-T[a]);
if (cmp(pm) < 0) neg++;
if (cmp(pm) > 0) pos++;
}
return (neg*pos == 0);
}

Graph

ErdsGallai theorem
A sequence of non-negative integers d1

dn can be represented as the degree sequence of a finite simple graph


on n vertices if and only if d1 + + dn is even and
k
X
i=1

di k(k

1) +

n
X

min(di , k)

i=k+1

holds for 1 k n.

Stable Marriage
a511
a511
5e20
68c0
6589
2baa
7fc7
7fc7
fc77
802c
07a0

#define maxn 512


int
int
int
int
int

W[maxn][maxn], M[maxn][maxn];
quem[maxn]; //quem[i] = homem q a mulher i casa
ja[maxn]; //ja[i] = mulher que o cara i casa
topo[maxn];
n;

bool prefere (int m, int novo, int velho){


for (int i = 0; i < n; i++){
if (W[m][i] == novo) return true;

ACM ICPC Reference, page 16

University of So Paulo

13ac
b334
4aa7
4aa7
4aa7
b9be
bb77
1b4d
07f4
2b4e
6ad6
b929
45ef
0227
203f
feff
3321
3a7c
2021
78d3
e453
5e2b
5e2b
17bb
a3d0
cd6d
6172
feda
19d4
52db
a790
eb1d
2bab
e7ef
3296
153e
b9ad
d607
cda2
2213
0a5d
5c21
26cb
b19c
7b3f
5840
5840
dec7
f516

if (W[m][i] == velho) return false;


}
}
void solve (){
bool flag = true;
while (1){
flag = true;
for (int i = 0; i < n; i++) if (ja[i]==-1){
flag = false;
int m = M[i][topo[i]++];
if (quem[m] == -1){
quem[m] = i; ja[i] = m;
}
else if (prefere (m, i, quem[m])){
ja[quem[m]] = -1, quem[m] = i; ja[i] = m;
}
}
if (flag) break;
}
}
int main (){
int t; scanf("%d", &t);
int aux;
while (t--){
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &aux);
for (int j = 0; j < n; j++){
scanf("%d", &M[i][j]), M[i][j]--;
}
}
for (int i = 0; i < n; i++){
scanf("%d", &aux);
for (int j = 0; j < n; j++){
scanf("%d", &W[i][j]), W[i][j]--;
}
}
memset (quem, -1, sizeof (quem));
memset (topo, 0, sizeof (topo));
memset (ja, -1, sizeof (ja));
solve();
for (int i = 0; i < n; i++) printf("%d %d\n", i+1, quem[i]+1);
}
return 0;
}

Dinic maxflow
d41d
d41d
d41d
469e
469e
1adb
1b9b
1b9b
3922
b25e
7173
47ea
d4ff
d4ff
bcdd
5509
dbcd
dbcd
dbcd
6358
0a1b
a469
2e59
6571
66ca
66ca
31a3
c9a4
fac6
ecd3
cc20
5524
b2fc
3a8a
1e8a
c984
2aa0
8b60
3c55
3322
9840
eb49
febd
c28a
0f3a
0f3a
dfab
bd70
4b3f
31a5
6de4
1b53
b77c

// Dinic maxflow, min(O(EV^2),O(maxflow*E)(?)) worst case


// O(E*min(V^2/3,sqrt(E))) for unit caps (O(E*sqrt(V)) if bipartite)
typedef ll FTYPE;

// define as needed

const int MAXV = ; // maximo numero de vertices


const FTYPE FINF = LINF; // infinite flow
struct Edge {
int to;
FTYPE cap;
Edge(int t, FTYPE c) { to = t; cap = c; }
};
vector<int> adj[MAXV];
vector<Edge> edge;
int ptr[MAXV], dinic_dist[MAXV];
// Inserts an edge u->v with capacity c
inline void add_edge(int u,int v,FTYPE c) {
adj[u].push_back(edge.size());
edge.push_back(Edge(v,c));
adj[v].push_back(edge.size());
edge.push_back(Edge(u,0)); // modify to Edge(u,c) if graph is non-directed
}
bool dinic_bfs(int _s,int _t) {
memset(dinic_dist,-1,sizeof(dinic_dist));
dinic_dist[_s] = 0;
queue<int> q;
q.push(_s);
while(!q.empty() && dinic_dist[_t] == -1) {
int v = q.front();
q.pop();
for(size_t a=0;a<adj[v].size();++a) {
int ind = adj[v][a];
int nxt = edge[ind].to;
if(dinic_dist[nxt] == -1 && edge[ind].cap) {
dinic_dist[nxt] = dinic_dist[v] + 1;
q.push(nxt);
}
}
}
return dinic_dist[_t] != -1;
}
FTYPE dinic_dfs(int v,int _t,FTYPE flow) {
if(v == _t) return flow;
for(int &a = ptr[v];a<(int)adj[v].size();++a) {
int ind = adj[v][a];
int nxt = edge[ind].to;
if(dinic_dist[nxt] == dinic_dist[v] + 1 && edge[ind].cap) {
FTYPE got = dinic_dfs(nxt,_t,min(flow,edge[ind].cap));

ACM ICPC Reference, page 17

University of So Paulo

b722
c013
d24b
8152
ba4c
0545
d9ee
bc36
c298
c298
1110
f3b1
351d
49e8
3d97
c875
da59
aeed
aeed
aeed
46d7
0db6
e3fc
38fc

if(got) {
edge[ind].cap -= got;
edge[ind^1].cap += got;
return got;
}
}
}
return 0;
}
FTYPE dinic(int _s,int _t) {
FTYPE ret = 0, got;
while(dinic_bfs(_s,_t)) {
memset(ptr,0,sizeof(ptr));
while((got = dinic_dfs(_s,_t,FINF))) ret += got;
}
return ret;
}
// Clears dinic structure
inline void dinic_clear() {
for(int a=0;a<MAXV;++a) adj[a].clear();
edge.clear();
}

Min-cost maxflow
d41d
d41d
d97f
e6a7
4551
4551
1c31
54b0
b6ba
b6ba
b844
b844
ba37
09c7
45f8
4417
2771
7093
7093
96f2
5234
c32a
c32a
c32a
4864

// Min-cost Max-flow ( O(V*E + V^2*MAXFLOW) )


typedef int FTYPE; // type of flow
typedef int CTYPE; // type of cost
typedef pair<FTYPE,CTYPE> pfc; // pair<flow,cost>
const int MAXV = ; // maximum number of vertices
const CTYPE CINF = INF; // infinite cost
const FTYPE FINF = INF; // infinite flow
void operator+=(pfc &p1,pfc &p2) { p1.first+=p2.first; p1.second+=p2.second; }
struct Edge {
int to;
FTYPE cap;
CTYPE cost;
Edge(int a,FTYPE cp,CTYPE ct) { to = a; cap = cp; cost = ct; }
};
vector<int> adj[MAXV];
vector<Edge> edge;
int V; // number of vertices (dont forget to set!)
// Inserts an edge u->v with capacity c and cost cst
inline void add_edge(int u,int v,FTYPE c,CTYPE cst) {

c4cf
aa3f
787c
f5c6
d0d9
d0d9
a5df
0045
bac0
ded6
ded6
f9d1
f123
7647
6410
1719
d96c
ea3c
4429
6092
cec9
2f1a
411c
0098
3046
3046
6793
405b
e94d
1f2b
8d6c
ec7b
6d38
8599
30a8
5370
ce7a
9ada
8afc
3b54
9de4
610c
1a34
31f8
71fb
e26d
3669
07af
5228
f290
2565
0577
6aaf
43c0
c20c

adj[u].push_back(edge.size());
edge.push_back(Edge(v,c,cst));
adj[v].push_back(edge.size());
edge.push_back(Edge(u,0,-cst));
}
FTYPE flow[MAXV];
CTYPE dist[MAXV], pot[MAXV];
int prv[MAXV], e_ind[MAXV];
bool foi[MAXV];
void bellman_ford(int _s) {
for(int a=0;a<V;++a) dist[a] = CINF;
dist[_s] = 0;
for(int st=0;st<V;++st) {
for(int v=0;v<V;++v) {
for(size_t a=0;a<adj[v].size();++a) {
int ind = adj[v][a];
int nxt = edge[ind].to;
if(!edge[ind].cap) continue;
dist[nxt] = min(dist[nxt],dist[v] + edge[ind].cost);
}
}
}
}
pfc dijkstra(int _s,int _t) { // O(V^2)
for(int a=0;a<V;++a) {
dist[a] = CINF;
foi[a] = 0;
}
dist[_s] = 0;
flow[_s] = FINF;
while(1) {
int v;
CTYPE d = CINF;
for(int a=0;a<V;++a) {
if(foi[a] || dist[a] >= d) continue;
d = dist[a];
v = a;
}
if(d == CINF) break;
foi[v] = 1;
for(size_t a=0;a<adj[v].size();++a) {
int ind = adj[v][a];
int nxt = edge[ind].to;
if(!edge[ind].cap || dist[nxt] <= dist[v] +
edge[ind].cost + pot[v] - pot[nxt]) continue;
dist[nxt] = dist[v] + edge[ind].cost + pot[v] - pot[nxt];
prv[nxt] = v;
e_ind[nxt] = ind;
flow[nxt] = min(flow[v],edge[ind].cap);
}
}
if(dist[_t] == CINF) return pfc(FINF,CINF);

ACM ICPC Reference, page 18

University of So Paulo

efac
de63
9208
e8c6
3e32
5464
f53a
1c33
3620
fc6b
fc6b
fc6b
c9d9
b783
24bc
4f45
8e0a
0045
0241
0241
0241
8377
e477
1245
8892

for(int a=0;a<V;++a) pot[a] += dist[a];


pfc ret(flow[_t],0);
for(int cur = _t; cur != _s; cur = prv[cur]) {
int ind = e_ind[cur];
edge[ind].cap -= flow[_t];
edge[ind^1].cap += flow[_t];
ret.second += flow[_t] * edge[ind].cost; // careful with overflow!
}
return ret;
}
// Returns a pair (max-flow, min-cost)
pfc mcmf(int _s,int _t) {
pfc ret(0,0), got;
bellman_ford(_s);
for(int a=0;a<V;++a) pot[a] = dist[a];
while( (got = dijkstra(_s,_t)).first != FINF ) ret += got;
return ret;
}
// Clears mcmf structure
inline void mcmf_clear() {
edge.clear();
for(int a=0;a<V;++a) adj[a].clear();
}

Finding one solution for 2SAT


1. Construct implication graph and contract it (it will be a skew-symmetric DAG)
2. Consider the vertices in topsort order. If it was not assigned a value, set its value to false. This causes all of
the terms in the complementary component to be set to true.
Due to the topological ordering, when a term x is set to false, all terms that lead to it via a chain of implications will
themselves already have been set to false. Symmetrically, when a term is set to true, all terms that can be reached
from it via a chain of implications will already have been set to true. Therefore, the truth assignment constructed
by this procedure satisfies the given formula.

3a33
b8b0 int StoerWagner() {
b942
int ret = INF;
3405
for(int siz=n;siz>1;--siz) {
26ba
for(int a=0;a<n;++a) {
7a96
sum[a] = 0;
7113
foi[a] = out[a];
5bae
}
daae
int i=0;
d6f7
while(1) {
13a0
int v,d=-1;
9ed3
for(int a=0;a<n;++a) {
d5a2
if(!foi[a] && sum[a] > d) {
ea58
d = sum[a];
4484
v = a;
10ae
}
296a
}
be90
if(d==-1) break;
49f4
foi[v] = 1;
5dac
ord[i++] = v;
7cc7
for(int a=0;a<deg[v];++a) {
a55e
int nxt = adj[v][a];
563c
if(!foi[nxt]) sum[nxt] += cost[v][nxt];
eea1
}
89ee
}
8607
int s = ord[siz-2], t = ord[siz-1];
10c1
ret = min(ret, sum[t]);
4d8d
out[t] = 1;
679e
for(int a=0;a<deg[t];++a) {
6290
int nxt = adj[t][a];
06ef
if(s==nxt) continue;
f771
if(cost[s][nxt]==0) {
1773
adj[s][deg[s]++] = nxt;
94fc
adj[nxt][deg[nxt]++] = s;
5c51
}
4c12
cost[s][nxt] += cost[t][nxt];
51ce
cost[nxt][s] += cost[nxt][t];
6fcb
}
d8c9
}
30d8
return ret;
e9e7 }

Stoer-Wagner algorithm for global mincut


d41d
d41d
d41d
d41d
431d
abbd
abbd
29e0
fb4f
d93b
3a33

//
//
//

Algoritmo de Stoer-Wagner
Encontra o corte minimo em um grafo
Complexidade: O(N^3)

const int INF = 0x3f3f3f3f;


const int MAXN = 110;
int adj[MAXN][MAXN], cost[MAXN][MAXN];
int deg[MAXN], sum[MAXN], ord[MAXN];
bool foi[MAXN], out[MAXN];
int n,m;

Maximum matching in generic graph


Edmonds algorithm: O(n3 )

d41d
d41d
d41d
50ac
50ac
5285
9124

// Edmonds Blossom Algorithm O(N^3)


// Finds maximum matching in generic graphs
const int MAXN = ;

// maximo numero de vertices

int n;
// numero de vertices
vector<int> adj[MAXN]; // lista de adj

ACM ICPC Reference, page 19

University of So Paulo

2a7d
fe16
cd46
cd46
3229
e3c9
0c59
eb63
a684
1ad4
8cdd
79f3
1750
0912
1b7d
a0f5
0a76
c88a
c88a
4072
a48d
f79f
3c8d
5ab4
efc3
0ac9
d657
d657
d969
c0ba
2939
7022
450a
b9c4
044c
6cd2
b731
7ab6
e2fd
8a3c
0cab
ab27
95e1
680e
7930
e755
7d5b
f4b3
9269
fa64
d079
0583
d224
5acb
f979

int match[MAXN];
// match[i] eh o par de i. -1 se nao tem par
int p[MAXN], base[MAXN] , q[MAXN];
bool used[MAXN], blossom[MAXN];
int lca ( int a, int b ) {
bool used [MAXN] = {0};
for ( ;; ) {
a = base [a];
used [a] = true;
if ( match[a] == -1 ) break;
a = p[match[a]];
}
for ( ;; ) {
b = base[b];
if ( used[b] ) return b;
b = p[match[b]];
}
}
void mark_path ( int v, int b, int children ) {
while ( base[v] != b ) {
blossom[base[v]] = blossom[base[match[v]]] = true;
p[v] = children;
children = match[v];
v = p[match[v]];
}
}
int find_path ( int root ) {
memset ( used, 0 , sizeof used );
memset ( p, - 1 , sizeof p );
for ( int i = 0 ; i < n ; ++i )
base[i] = i;
used[root] = true;
int qh = 0 , qt = 0;
q[qt++] = root;
while ( qh < qt ) {
int v = q[qh++];
for ( size_t i = 0; i < adj[v].size(); ++i ) {
int to = adj[v][i];
if ( base[v] == base[to] || match[v] == to ) continue;
if ( to == root || match[to] != -1 && p[match[to]] != -1 ) {
int curbase = lca ( v, to );
memset ( blossom, 0 , sizeof blossom );
mark_path ( v, curbase, to );
mark_path ( to, curbase, v );
for ( int i = 0 ; i < n ; ++i ) {
if ( blossom[base[i]] ) {
base[i] = curbase;
if ( !used[i] ) {
used[i] = true;
q[qt++] = i;
}
}
}

b476
398f
6af0
b064
1172
7e68
ec93
82f8
333d
1362
f167
120f
38fd }
38fd
b5b7 int
b5b7
326e
326e
c118
f9fa
7257
0c38
877f
9af3
6223
527f
95ab
6d85
8796
5da4
d98e
8ba9
039e
55b1
5729
ab71
b34d
be6f
2db7
2db7
110d }

}
else if ( p[to] == -1 ) {
p[to] = v;
if ( match[to] == -1 )
return to;
to = match[to];
used[to] = true;
q[qt++] = to;
}
}
}
return -1;
main() {
// ler grafo
memset ( match, -1 , sizeof match );
// otimizacao: comeca com um matching parcial guloso
for ( int i = 0 ; i < n ; ++i ) {
if ( match[i] == -1 ) {
for ( size_t j = 0 ; j < adj[i].size() ; ++j ) {
if ( match[ adj[i][j] ] == -1 ) {
match[ adj[i][j] ] = i;
match[i] = adj[i][j];
break;
}
}
}
}
for ( int i = 0 ; i < n ; ++ i ) {
if ( match[i] == - 1 ) {
int v = find_path(i);
while ( v != -1 ) {
int pv = p[v], ppv = match[pv];
match[v] = pv, match[pv] = v;
v = ppv;
}
}
}
// ...

Tarjans algorithm for Strongly Connected Components


d41d
1972
830e
4e54
45c6
c06f
bf13

// Precisa de adj[MAXN][MAXN], deg[MAXN] (lista de adjacencias)


int cmp[MAXN];
// Em qual componente esta o vertice i
int ind[MAXN],low[MAXN],cnt,cont; // Zerar vetor ind com -1 !!! <-----bool inStack[MAXN];
stack<int> st;
void tarjan(int v) {

ACM ICPC Reference, page 20

University of So Paulo

b69c
5387
471e
3b9d
d9cf
329e
65c3
1da7
9394
0cdb
6ad9
5a5c
6e2f
ff4b
c01c
a0cd
43d7
01d6
b008
8e76
c759
dac1 }

ind[v] = low[v] = cnt++;


st.push(v);
inStack[v] = 1;
for(int a=0;a<deg[v];++a) {
int nxt = adj[v][a];
if(ind[nxt] == -1) {
tarjan(nxt);
low[v] = min(low[v],low[nxt]);
}
else if(inStack[nxt]) low[v] = min(low[v],ind[nxt]);
}
if(ind[v] == low[v]) {
int vv;
do {
vv = st.top();
st.pop();
inStack[vv] = 0;
cmp[vv] = cont;
} while(vv != v);
++cont;
}

Articulation point and Bridges


7d7d
e083
a811
a811
b954
634d
3095
757a
1a10
f611
8aae
ca72
da43
cba9
9627
4ce6
4ce6
339f
a92f
acae
3be5
5642
cc0a
cc0a
162a
c2ee
9663

int ind[MAXN],low[MAXN]; // Zerar ind com -1! <----------------int cnt;


// Zerar!
<----------------// Chamar com prev = -1
void bap_dfs(int v,int prev) {
ind[v] = low[v] = cnt++;
int cont = 0;
bool flag = 0;
for(int a=0;a<adj[v].size();++a) {
int nxt = adj[v][a];
if(ind[nxt] == -1) {
++cont;
bap_dfs(nxt,v);
low[v] = min(low[v],low[nxt]);
if(low[nxt] >= ind[v]) flag = 1;
if(low[nxt] == ind[nxt]) {
// v-nxt eh uma ponte
}
}
else if(nxt != prev) low[v] = min(low[v],ind[nxt]);
}
if(prev == -1) {
if(cont > 1) {
// v eh um ponto de articulacao
}
}
else if(flag) {

9663
1c41
85ab }

// v eh um ponto de articulacao
}

Strings

Aho-Corasick
1ec0
0176
631f
ed2d
ed2d
b5eb
b5eb
da6a
afc3
f085
b391
d26c
8816
404a
ceb6
0749
0749
e6be
a46c
0498
d60a
601a
db6c
a687
7125
b451
6ce2
1aff
90ab
ed7d
eae4
b5dc
44a0
e3ee
1532

#define
#define
#define
#define

MAXS 1000
MAXT 100000
MAX 100000
cc 52

int T[MAX], term[MAX], sig[MAX][cc], cnt;


void add (char s[MAXS], int id){
int x = 0, n = strlen(s);
for (int i = 0; i < n; i++){
int c = s[i]-A;
if (sig[x][c] == 0) term[cnt] = 0, sig[x][c] = cnt++;
x = sig[x][c];
}
term[x] = 1;
}
void aho (){
queue <int> Q;
for (int i = 0; i < cc; i++){
int v = sig[0][i];
if (v) Q.push (v), T[v] = 0;
}
while (!Q.empty()){
int u = Q.front(); Q.pop();
for (int i = 0; i < cc; i++){
int x = sig[u][i];
if (x == 0) continue;
int v = T[u];
while (sig[v][i] == 0 && v != 0) v = T[v];
int y = sig[v][i];
Q.push(x), T[x] = y, term[x] |= term[y];
}
}
}

Manachers algorithm for finding longest palindromic substring


8eac
b90a
b90a
b90a

char s[200000];
int n;
// Encontrar palindromos - inicializa d1 e d2 com zeros, e eles guadram
// o numero de palindromos centrados na posicao i (d1[i] e d2[i])

ACM ICPC Reference, page 21

University of So Paulo

b90a
0245
6103
adee
e50f
96d1
b185
7404
86ca
7b9c
e5c3
9a4e
9a4e
61d8
f943
5ec6
1a46
4712
b698
1f61
7e38
7a76
d167

// impar
int d1[200000], d2[200000];
void imp(){
int l=0, r=-1;
for (int i=0; i<n; ++i) {
int k = (i>r ? 0 : min (d1[l+r-i], r-i)) + 1;
while (i+k < n && i-k >= 0 && s[i+k] == s[i-k]) ++k;
d1[i] = --k;
if (i+k > r)
l = i-k, r = i+k;
}
}
// par
void par(){
int l=0, r=-1;
for (int i=0; i<n; ++i) {
int k = (i>r ? 0 : min (d2[l+r-i+1], r-i+1)) + 1;
while (i+k-1 < n && i-k >= 0 && s[i+k-1] == s[i-k]) ++k;
d2[i] = --k;
if (i+k-1 > r)
l = i-k, r = i+k-1;
}
}

Sux array
e9bf
e9bf
0bf5
b7a0
b7a0
b7a0
b7a0
b7a0
b7a0
c70a
c70a
759d
e78c
f2ec
fbe8
dcaa
b346
128a
fbac
53fc
bd68
eb4b
9d6a
94a0
978e
7bfc

#define MAXN 1000005


int n,t; //n es el tamano de la cadena
int p[MAXN],r[MAXN],h[MAXN];
//p es el inverso del suffix array, no usa indices del suffix array ordenado,
//p[i] eh a ordem do sufixo que comeca na posicao i
//h el el tamano del lcp entre el i-esimo y el i+1-esimo elemento de
//suffix array ordenado
//r eh o vetor inverso
string s;
void fix_index(int *b, int *e) {
int pkm1, pk, np, i, d, m;
pkm1 = p[*b + t];
m = e - b; d = 0;
np = b - r;
for(i = 0; i < m; i++) {
if (((pk = p[*b+t]) != pkm1) && !(np <= pkm1 && pk < np+m)) {
pkm1 = pk;
d = i;
}
p[*(b++)] = np + d;
}
}
bool comp(int i, int j) {
return p[i + t] < p[j + t];

4948
16f8
38ec
bc0a
4b4b
4b4b
53a1
53a1
b4b7
9ac6
e803
8552
0c03
c9e6
2227
1631
40ba
6b94
399c
c661
a7d9
4163
264b
dca2
cde0
9c7d
07c5
8107
dfb9
1c1e
3f74
6aa9
6aa9
6aa9
6aa9
c9c7
b858
04ef
e889
e84b
995d
3362
5cc9
493f
f31c
b6d1
f49d
00f3
1b8d
0486

}
void suff_arr() {
int i, j, bc[256];
t = 1;
for(i = 0; i < 256; i++) bc[i] = 0;

//alfabeto

for(i = 0; i < n; i++) ++bc[int(s[i])]; //counting sort inicial del alfabeto


for(i = 1; i < 256; i++) bc[i] += bc[i - 1];
for(i = 0; i < n; i++) r[--bc[int(s[i])]] = i;
for(i = n - 1; i >= 0; i--) p[i] = bc[int(s[i])];
for(t = 1; t < n; t *= 2) {
for(i = 0, j = 1; i < n; i = j++) {
while(j < n && p[r[j]] == p[r[i]]) ++j;
if (j - i > 1) {
sort(r + i, r + j, comp);
fix_index(r + i, r + j);
}
}
}
}
void lcp() {
int tam = 0, i, j;
for(i = 0; i < n; i++) if (p[i] > 0) {
j = r[p[i] - 1];
while(s[i + tam] == s[j + tam]) ++tam;
h[p[i] - 1] = tam;
if (tam > 0) --tam;
}
h[n - 1] = 0;
}
int main(void){
//suff_arr();
//lcp();
//
cin >> s;
s += $; //un caracter menor a todos para que no afecte el resultado
n = s.size();
suff_arr();
for (int i = 0; i < n; i++){
printf("%d ", p[i]);
}
printf("\n\n");
lcp();
for (int i = 0; i < n; i++){
printf("%d ", h[i]);
}
printf("\n");
return 0;
}

ACM ICPC Reference, page 22

University of So Paulo

Knuth-Morris-Pratt algorithm
33c2
5f1e
ab34
245b
93f5
8dad
2b5b
7fbd
7186
3e31
dc81
89d1
6c79
3ad8
48f3
d73c
63e2
11d9
0562
c0b7
51a9
f206
4675
15df
2e00
3f8e
3f8e
56a6
d8c1
0744
c9ce
54c5
4846
6d09
bb49
4c96
2a3b
25d0
eb70
f16c
1f75
938a
49a4
a285
abdb

class KMP {
private:
string pattern;
int len;
public:
vector<int> f;
KMP(string p) {
pattern = p;
len = p.size();
f.resize(len+2);
f[0] = f[1] = 0;
for(int a=2;a<=len;++a) {
int now = f[a-1];
while(1) {
if(p[now] == p[a-1]) {
f[a] = now+1;
break;
}
if(now==0) {
f[a] = 0;
break;
}
now = f[now];
}
}
}
//returns a vector of indices with the beginning of each match
vector<int> match(string text) {
vector<int> ret;
int size = text.size();
int i=0,j=0;
while(j<size) {
if(text[j] == pattern[i]) {
++i; ++j;
if(i==len) {
ret.push_back(j-len);
i = f[i];
}
}
else if(i>0) i = f[i];
else j++;
}
return ret;
}
};

Hash
dc9a typedef char HType;
dc9a

0c12
0c12
ec30
d084
0d28
0f7b
b917
afbc
ac5b
547d
3369
8aaa
f1f5
674f
6710
ba95
e26c
1895
b83d
c53d
bb50
56f7
56f7
2b89
2b89
5df8
bd84
c2d0
d0df
8ace
6231
ab47
ecc9
4d55
6b7f
26eb
26eb
aa1a
bda8
65e1
0e4b

const int P1 = 31, P2 = 37, MOD = (int)1e9 + 7;


struct Hash {
ll h1, h2;
Hash(ll a = 0, ll b = 0) { h1 = a; h2 = b; }
void append(HType c) {
h1 = (P1*h1 + c) % MOD;
h2 = (P2*h2 + c) % MOD;
}
bool operator== (Hash that) const {
return h1 == that.h1 && h2 == that.h2;
}
bool operator!= (Hash that) const {
return h1 != that.h1 || h2 != that.h2;
}
Hash operator* (Hash that) const {
return Hash((h1*that.h1)%MOD, (h2*that.h2)%MOD);
}
Hash operator- (Hash that) const {
return Hash( (h1 - that.h1 + MOD)%MOD, (h2 - that.h2 + MOD)%MOD);
}
};
Hash pot[MAXN];
vector<Hash> build_hash(int n, HType *v) {
pot[0] = Hash(1,1);
vector<Hash> ret;
Hash acc;
for(int i = 0; i < n; i++) {
acc.append(v[i]);
ret.push_back(acc);
if(i > 0) pot[i] = pot[i-1] * Hash(P1, P2);
}
return ret;
}
inline Hash get_hash(int l, int r, vector<Hash> &hashv) {
if(l == 0) return hashv[r];
return hashv[r] - hashv[l-1] * pot[r-l+1];
}

Z-algorithm
d41d
d41d
d41d
dfb2
297a
d7d5
57ec
e35e

// Z-algorithm, O(N)
// Builds array z such that z[i] = size of longest prefix substring
// starting at index i
vector<int> Z(string s) {
vector<int> z(1,s.size());
int l=0,r=0;
for(int a=1;a<(int)s.size();++a) {
if(r < a) {

ACM ICPC Reference, page 23

University of So Paulo

ae49
8690
ea6e
e7b0
9141
4f00
cae0
d3a9
552c
657f
0258
7bee
f580
f2fc
c455 }

10

l = r = a;
while(r<(int)s.size() && s[r] == s[r-l]) ++r;
z.push_back(r-l);
r--;
}
else if(z[a-l] < r-a+1) z.push_back(min<int>(z[a-l],s.size()-a));
else {
l = a;
while(r<(int)s.size() && s[r] == s[r-l]) ++r;
z.push_back(r-l);
r--;
}
}
return z;

Data structures

Static Range Minimum Query


3dd1
8592
dc31
dc31
dc31
8f76
babe
ed78
1a88
8012
7f02
5a08
b394
b394
3fde
6e47
ef17
173e
11eb

int rmq[LOG][MAXN];
int v[MAXN];
int n;
// Builds RMQ structure for array v of size n in O(n*log(n))
void build_rmq() {
for(int i = 0; i < n; i++)
rmq[0][i] = v[i];
for(int log = 1; log < LOG; ++log)
for(int i = 0; i < n; i++)
rmq[log][i] = min(rmq[log-1][i],
rmq[log-1][min(n-1, i + (1<<(log-1)))]);
}
// l e r inclusives
int get_rmq(int l,int r) {
int len = r - l + 1;
int bit = 31 - __builtin_clz(len);
return min(rmq[bit][l], rmq[bit][r - (1<<bit) + 1]);
}

2D Longest Increasing Subsequence


6cdc
9745
c458
0343
0343
1d06
b9bf
54ac

struct ponto{
int x,y;
bool operator <(const ponto& p) const { return x<p.x; }
};
ponto v[MAXN];
set<ponto> m[MAXN];
set<ponto> :: iterator it;

bde8
bde8
5fe8
ffbb
9fd2
6696
de4f
1b6e
c573
0390
b739
55fc
a393
a393
cf14
2c2c
d3ba
a479
a0ee
584d
7dcf
d9e1
d9e1
5c14
6c55
7bdd
7c8a
985b
41ae
0941
4e53
e33a
7916
ff35
927a
f8a9
8fb5

int n, t;
void insere(int p, ponto c){
if(p>t)t++;
it = m[p].lower_bound(c);
vector< ponto > tira;
for(;it!=m[p].end();it++){
if(it->y >= c.y) tira.pb(*it);
else break;
}
for(int j=0;j<sz(tira);j++) m[p].erase(tira[j]);
m[p].insert(c);
}
bool cabe(int p, int i){
if(p==0) return false;
if(p==t+1) return true;
it = m[p].lower_bound(v[i]);
if(it == m[p].begin()) return true;
it--;
return v[i].y <= it->y;
}
int lis(){
t=0;
f (i, 0, n) m[i].clear();
for(int i=0;i<n;i++){
int l=0,r=t+1, j;
while(l!=r){
j = (l+r)/2;
if(!cabe(j,i)) l=j+1;
else r=j;
}
insere(l,v[i]);
}
return t;
}

Treap
d41d // Supports insertion, deletion, querying kth-element and finding element
d41d // Keeps duplicate elements as different nodes
d41d
10aa template <class T> class Treap {
d02a
struct Node {
a39f
T val;
2112
int h,cnt;
bfcc
Node *l, *r;
588c
Node(T val2) {
ed02
val = val2;
1501
h = rand();
e0eb
cnt = 1;

University of So Paulo

cd33
b66b
cb40
0efa
6510
2612
e761
d4ef
b26d
f737
74a9
205f
2a7b
1885
993f
731b
1f9e
b3c9
7762
b75b
aca0
cc9c
ed45
7741
f999
203f
6a29
19fb
930c
60c7
0531
da12
1663
dcd3
325a
757d
a155
721a
a9d0
43b5
6cd0
f742
4efc
79b4
1704
5c1f
5e00
ca41
02b9
0301
9863
7961
9103
a81a
a81a

l = r = NULL;
}
};
Node *root;
inline Node* newNode(T val) { return new Node(val); }
inline void refresh(Node *node) {
if(node == NULL) return;
node->cnt = (node->l == NULL ? 0 : node->l->cnt) +
(node->r == NULL ? 0 : node->r->cnt) + 1;
}
void _insert(Node *&node, T val) {
if(node == NULL) {
node = newNode(val);
return;
}
if(val <= node->val) {
_insert(node->l, val);
if(node->l->h > node->h) {
Node *aux = node->l;
node->l = aux->r;
aux->r = node;
node = aux;
refresh(node->r);
refresh(node);
}
else refresh(node);
}
else {
_insert(node->r, val);
if(node->r->h > node->h) {
Node *aux = node->r;
node->r = aux->l;
aux->l = node;
node = aux;
refresh(node->l);
refresh(node);
}
else refresh(node);
}
}
Node* merge(Node *L,Node *R) {
if(L == NULL) return R;
if(R == NULL) return L;
if(L->h < R->h) {
L->r = merge(L->r,R);
refresh(L);
return L;
}
else {
R->l = merge(L,R->l);
refresh(R);
return R;
}
}
// not used. splits node into two trees a(<=val) and b(>val)

ACM ICPC Reference, page 24

314d
void split(T val, Node *node, Node *&a, Node *&b) {
05c5
if(node == NULL) {
5cdb
a = b = NULL;
069b
return;
f1a9
}
0f67
Node *aux;
496e
if(val > node->val) {
44c0
split(val,node->r,aux,b);
c4a9
node->r = aux;
2145
a = node;
d30c
refresh(a);
64c5
}
4bca
else {
6a72
split(val,node->l,a,aux);
372d
node->l = aux;
426d
b = node;
f8ae
refresh(b);
cfb4
}
79c4
}
79c4
// erases a single appearence of val
42f8
void _erase(Node *&node, T val) {
f6ee
if(node == NULL) return;
3a82
if(node->val > val) _erase(node->l, val);
70b2
else if(node->val < val) _erase(node->r, val);
bdea
else node = merge(node->l,node->r);
323c
refresh(node);
8fb2
}
8fb2
// 0-indexed (not safe if element doesnt exist)
9fa7
int _kth(Node *node,int k) {
3a77
int ql = (node->l == NULL ? 0 : node->l->cnt);
efe4
if(k < ql) return _kth(node->l,k);
7072
if(k == ql) return node->val;
209f
k -= ql + 1;
61e3
return _kth(node->r,k);
1509
}
1509
// returns position (0-indexed) of element val. -1 if it doesnt exist
560f
int _find(Node *node, T val) {
5713
if(node == NULL) return -1;
d526
if(node->val == val) return (node->l == NULL ? 0 : node->l->cnt);
d502
else if(node->val > val) return _find(node->l,val);
2893
else {
7cec
int pos = _find(node->r,val);
53a4
if(pos == -1) return -1;
76f9
return 1 + (node->l == NULL ? 0 : node->l->cnt) + pos;
509e
}
d04b
}
d07b
void _clear(Node *&node) {
3224
if(node == NULL) return;
7ad7
_clear(node->l); _clear(node->r);
6120
delete node;
c349
node = NULL;
46e2
}
bdb0 public:
06c9
Treap() { root = NULL; }
0b2f
void insert(T val) { _insert(root,val); }

ACM ICPC Reference, page 25

University of So Paulo

547c
4978
7544
6986
ac7e
a350 };

int kth(int k) { return _kth(root,k); }


int size() { return root == NULL ? 0 : root->cnt; }
void clear() { _clear(root); }
void erase(T val) { _erase(root,val); }
int find(T val) { return _find(root,val); }

KD-Tree
be52
e3bf
a0fa
d25b
b9f7
cc29
1152
1152
149d
5e32
8257
6a86
6a86
dcaf
e3e5
d2e9
7b48
2fe5
d31e
d31e
f38d
777c
ce32
0982
26c3
74d7
d403
1a75
c8c3
c8c3
41fd
9124
d0f8
598d
b820
799c
406c
d9c3
a157
375a
375a
1a75
7d28

struct point {
ll x, y, z;
point(ll x=0, ll y=0, ll z=0): x(x), y(y), z(z) {}
point operator-(point q) { return point(x-q.x, y-q.y, z-q.z); }
ll operator*(point q) { return x*q.x + y*q.y + z*q.z; }
};
typedef vector<point> polygon;
struct KDTreeNode {
point p;
int level;
KDTreeNode *below, *above;
KDTreeNode (const point& q, int levl) {
p = q;
level = levl;
below = above = 0;
}
~KDTreeNode() { delete below, above; }
int diff (const point& pt) {
switch (level) {
case 0: return pt.x - p.x;
case 1: return pt.y - p.y;
case 2: return pt.z - p.z;
}
return 0;
}
ll distSq (point& q) { return (p-q)*(p-q); }
int rangeCount (point& pt, ll K) {
int count = (distSq(pt) < K*K) ? 1 : 0;
int d = diff(pt);
if (-d <= K && above != 0)
count += above->rangeCount(pt, K);
if (d <= K && below != 0)
count += below->rangeCount(pt, K);
return count;
}
};
class KDTree {
public:

106f
130c
a4ad
f095
91b1
7cf8
14e0
5d49
3061
e8ab
2035
2035
2035
fee1
890b
f4d3
f807
e5bf
8eb5
8eb5
f1ed
544a
c821
b93b
a894
937f
23aa
f1db
f750
9ba3
ee91
e0eb
d4e8
247d
36e9
8ced
5747
dd9f
ca38
ca38
d70e
1a3c
20fc
2efb
e672
8293
0fbb
9912
7ce5
faf5
e75f
6ada
ae2c
77c1
c2ab

polygon P;
KDTreeNode *root;
int dimention;
KDTree() {}
KDTree(polygon &poly, int D) {
P = poly;
dimention = D;
root = 0;
build();
}
~KDTree() { delete root; }
//count the number of pairs that has a distance less than K
ll countPairs(ll K) {
ll count = 0;
f(i, 0, P.size())
count += root->rangeCount(P[i], K) - 1;
return count;
}
protected:
void build() {
random_shuffle(all(P));
f(i, 0, P.size()) {
root = insert(root, P[i], -1);
}
}
KDTreeNode *insert(KDTreeNode* t, const point& pt, int parentLevel) {
if (t == 0) {
t = new KDTreeNode (pt, (parentLevel+1) % dimention);
return t;
} else {
int d = t->diff(pt);
if (d <= 0) t->below = insert (t->below, pt, t->level);
else t->above = insert (t->above, pt, t->level);
}
return t;
}
};
int main() {
int n, k;
point e;
polygon p;
while (cin >> n >> k && n+k) {
p.clear();
f(i, 0, n) {
cin >> e.x >> e.y >> e.z;
p.pb(e);
}
KDTree tree(p, 3);
cout << tree.countPairs(k) / 2LL << endl;
}
return 0;
}

You might also like