0% found this document useful (0 votes)
8 views

biblioteca

Uploaded by

llost031
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

biblioteca

Uploaded by

llost031
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Template Problema de Josephus O(n)

#include<bits/stdc++.h> //n: número de pessoas


using namespace std; //k: k-1 pessoas são poupadas e a k-ésima é executada
#define sc(a) scanf("%d", &a) int jos(int n,int k){
#define sc2(a, b) scanf("%d%d", &a, &b) if(n==1) return 1;
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c) return (jos(n-1,k)+(k-1))%n+1;
#define pri(x) printf("%d\n", x) }
#define prie(x) printf("%d ",x)
#define fi first Problema de Josephus O(log(n)), k=2
#define se second
#define mp make_pair int jos2(int n)
#define pb push_back {
#define BUFF ios::sync_with_stdio(false) int a=1;
#define db(x) cerr << #x << " == " << x << endl while(a<n) a=a*2;
typedef long long int ll; return ((2*n)-a)%n+1;
typedef long double ld; }
typedef pair<int, int> ii;
typedef vector<int> vi;
Fenwick Tree (BIT)
typedef vector<ii> vii;
const int INF = 0x3f3f3f3f; ll FT[MAXN+1];
const ll LINF = 0x3f3f3f3f3f3f3f3fll; int N;
const ld pi = acos(-1); void add(int a,ll v)
int main() {
{ for(;a<=N;a+=a&(-a)) FT[a]+=v;
return 0; }
} ll get(int a)
{
ll sum=0;
for(;a>0;a-=a&(-a)) sum+=FT[a];
return sum;
}
ll get_range(int a,int b)
{
return get(b)-get(a-1);
}
Fenwick Tree (Range Update) Inverso em Módulo (Euclides Extendido):
//FT1 -> FENWICK TREE //Encontra o inverso de a módulo m
//FT2 -> FENWICK TREE AUXILIAR int modInverse(int a, int m)
// n -> número de elementos {
// a,b - > range int m0 = m, t, q;
// v -> valor a ser somado int x0 = 0, x1 = 1;
void add(ll *FT,int p,ll v,int n) if (m == 1)
{ return 0;
for(;p<=n;p+=(p&(-p))) while (a > 1)
{ {
FT[p]+=v; // q is quotient
} q = a / m;
} t = m;
ll get(ll *FT,int p) // m is remainder now, process same as
{ // Euclid's algo
ll sum=0; m = a % m, a = t;
for(;p>0;p-=(p&(-p))) t = x0;
{ x0 = x1 - q * x0;
sum+=FT[p]; x1 = t;
} }
return sum; // Make x1 positive
} if (x1 < 0)
void add_range(ll *FT1,ll *FT2,int a,int b,ll v,int n) x1 += m0;
{ return x1;
add(FT1,a,v,n); }
add(FT1,b+1,-v,n); String Split (Útil):
add(FT2,a, v*(a-1),n);
add(FT2,b+1,-v*b,n);
} vector<string> split(string str, char del)
ll get_range(ll *FT1,ll *FT2,int a,int b,int n) {
{ vector<string> vec;
a--; stringstream ss(str);
return (get(FT1, b)*b -get(FT2, b)) - (get(FT1, string tok;
a)*a - get(FT2, a)); while(getline(ss, tok, del)) vec.push_back(tok);
} return vec;
}
Gambler’s Ruin Max Matching para grafo bipartido (Método Húngaro)
//Em cada turno, o perdedor cede uma moeda ao oponente // Complexidade O(n^3)
//Retorna a probabilidade de 1 ganhar o jogo vi G[MAXN];
double gamblersR(double p,int n1,int n2){ int match[MAXN];
double q=1-p; bool vis[MAXN];
if(p==0.5) return n1/double(n1+n2); int dfs(int v)
//probabilidades iguais {
return (1 - power((q/p),n1)) / (1 - if(vis[v]) return 0; //nao houve match
power((q/p),n1+n2)); vis[v]=true;
} for(int i=0;i<G[v].size();i++)
Longest Increasing Subsequence (LIS) O(n log(n)) {
int va=G[v][i];
if(match[va]==-1 || (dfs(match[va]))) //achou
int aux[MAXN],endLis[MAXN];
{
//usar upper_bound se puder >=
match[va]=v; //armazena o match
vi LisRec(vi v){
return 1;
int n=v.size();
}
int lis=0;
}
for (int i = 0; i < n; i++){
return 0;
int it = lower_bound(aux, aux+lis, v[i]) - aux;
}
endLis[i] = it+1;
int maxMatch(int n,int m) //tamanho dos conjuntos
lis = max(lis, it+1);
{
aux[it] = v[i];
for(int i=0;i<m;i++)
}
match[i]=-1;
vi resp;
int ret=0;
int prev=INF;
for(int i=0;i<n;i++)
for(int i=n-1;i>=0;i--){
{
if(endLis[i]==lis && v[i]<=prev){
for(int j=0;j<n;j++)
lis--;
vis[j]=false; //zera os visitados
prev=v[i];
ret+=dfs(i);//procura novo match a partir de i
resp.pb(i);
}
}
return ret;
}
}
reverse(resp.begin(),resp.end());
return resp;
}
Persistent Fenwick Tree (com timestamp) KMP (String Matching) O(n+m)
char T[MAX_N], P[MAX_N]; // T = text, P = pattern
vector<pair<int,ll> > FT[MAXN]; int b[MAX_N], n, m; // b = back table, n = length of T,
int v[MAXN]; m = length of P
int n; void pre()
void add(int i,int v,int time) {
{ int i = 0, j = -1;
for(;i<=n;i+=i&(-i)) b[0] = -1;
{ while (i < m)
ll last=FT[i].back().se; {
FT[i].pb(mp(time,last+v)); while (j >= 0 && P[i] != P[j]) j = b[j];
} //diferentes, reseta j usando b
} i++; j++; // se iguais, avança os 2 ponteiros
ll get(int i,int time) b[i] = j;
{ }
ll ret=0; }
for(;i>0;i-=i&(-i)) void kmp()
{ {
int pos= pre(); //monta a tabela de P
upper_bound(FT[i].begin(),FT[i].end(),mp(time,INFLL))- int i = 0, j = 0;
FT[i].begin()-1; while (i < n) //procura P em T
ret+=FT[i][pos].se; {
} while (j >= 0 && T[i] != P[j]) j = b[j];
return ret; //diferentes, reseta j usando b
} i++; j++; // se iguais, avança os 2 ponteiros
ll getRange(int a,int b,int time) if (j == m)
{ {
return get(b,time)-get(a-1,time); printf("Found at %d\n", i - j);
} j = b[j]; // prepara j para o próximo
possível match
}
}
}
int u = q.front();
Max Flow (Dinic do Dilson) O(V^2E) q.pop();
for(vector<Edge>::iterator
struct Edge e=g[u].begin();e!=g[u].end();e++)
{ {
int v, rev; if(not e->cap or level[e->v] != -1)
int cap; continue;
Edge(int v_, int cap_, int rev_) : v(v_), level[e->v] = level[u] + 1;
rev(rev_), cap(cap_) {} if(e->v == sink) return true;
}; q.push(e->v);
}
struct MaxFlow }
{ return false;
vector<vector<Edge> > g; }
vector<int> level;
queue<int> q; int blockingFlow(int u, int sink, int f)
int flow, n; {
if(u == sink or not f) return f;
MaxFlow(int n_) : g(n_), level(n_), n(n_) {} int fu = f;
for(vector<Edge>::iterator
void addEdge(int u, int v, int cap) e=g[u].begin();e!=g[u].end();e++)
{ {
if(u == v) return; if(not e->cap or level[e->v] != level[u] +
Edge e(v, cap, int(g[v].size())); 1) continue;
Edge r(u, 0, int(g[u].size())); int mincap = blockingFlow(e->v, sink,
g[u].push_back(e); min(fu, e->cap));
g[v].push_back(r); if(mincap)
} {
g[e->v][e->rev].cap += mincap;
bool buildLevelGraph(int src, int sink) e->cap -= mincap;
{ fu -= mincap;
fill(ALL(level), -1); }
while(not q.empty()) q.pop(); }
level[src] = 0; if(f == fu) level[u] = -1;
q.push(src); return f - fu;
while(not q.empty()) }
{
int maxFlow(int src, int sink){ int mid=(l+r)/2;
flow = 0; return
while(buildLevelGraph(src, sink)) max(query(2*pos+1,l,mid,ql,qr),query(2*pos+2,mid+1,r,ql
flow+= blockingFlow(src, sink, ,qr));
numeric_limits<int>::max()); }
return flow; void update(int pos,int l,int r,int i,int k){
} if(l>i or r<i)return;
}; if(l==r){
Heavy-Light Decompositon arr[i]=k;
st[pos]=arr[i];
return;
//HLD maior aresta no caminho, com update }
int st[4*MAXN];//seg tree int mid=(l+r)/2;
int arr[MAXN];//array para montar segtree update(2*pos+1,l,mid,i,k);
ii edge[MAXN]; update(2*pos+2,mid+1,r,i,k);
vii G[MAXN]; st[pos]=max(st[2*pos+1],st[2*pos+2]);
int subt[MAXN];//tamanho da sub-arvore }
int par[MAXN];//pai no dfs, usado para subir na HLD void dfs(int v,int p){
int chainHead[MAXN];//cabeca da chain na HLD subt[v]=1;
int tot;//numero de chains par[v]=p;
int currPos;//posicao no global array int mx=0;
int posInArr[MAXN]; //posicao de v no array for(int i=0;i<G[v].size();i++){
int chainNum[MAXN]; //numero da chain de v int va=G[v][i].fi;
int heavyChild[MAXN]; //filho pesado de v if(va!=p){
void build(int pos,int l,int r){ dfs(va,v);
if(l==r){ subt[v]+=subt[va];
st[pos]=arr[l]; if(subt[va]>mx){
return; mx=subt[va];
} heavyChild[v]=va;
int mid=(l+r)/2; }
build(2*pos+1,l,mid); }
build(2*pos+2,mid+1,r); }
st[pos]=max(st[2*pos+1],st[2*pos+2]); }
} int hld(int v,int costP,int p){
int query(int pos,int l,int r, int ql,int qr){ if(chainHead[tot]==-1)
if(l>=ql && r<=qr)return st[pos]; chainHead[tot]=v;
if(l>qr or r<ql)return 0; chainNum[v]=tot;
posInArr[v]=currPos; build(0,0,n-1);
arr[currPos++]=costP; char s[100];
for(int i=0;i<G[v].size();i++){ int q;
int va=G[v][i].fi; sc(q);
int cost=G[v][i].se; while(q--){
if(va==heavyChild[v]) int op;
hld(va,cost,v); sc(op);
} int a,b;
for(int i=0;i<G[v].size();i++){ if(op==1){
int va=G[v][i].fi; int id,x;
int cost=G[v][i].se; sc2(id,x);
if(va!=p && va!=heavyChild[v]){ id--;
tot++;//nova chain a=edge[id].fi;
hld(va,cost,v); b=edge[id].se;
} if(a==par[b])swap(a,b);
} update(0,0,n-1,posInArr[a],x);
} }
int main(){ else{
int n; sc2(a,b);
sc(n); a--,b--;
for(int i=0;i<n;i++){ int ret=-INF;
G[i].clear(); while(chainNum[a]!=chainNum[b]){
chainHead[i]=-1; if(chainNum[a]<chainNum[b])
heavyChild[i]=-1; swap(a,b);
} ret=max(ret,query(0,0,n-
tot=0; 1,posInArr[chainHead[chainNum[a]]],posInArr[a]));
currPos=0; a=par[chainHead[chainNum[a]]];
for(int i=0;i<n-1;i++){ }
int a,b,c; if(posInArr[a]>posInArr[b])
sc3(a,b,c); swap(a,b);
a--,b--; ret=max(ret,query(0,0,n-
G[a].pb(mp(b,c)); 1,posInArr[a]+1,posInArr[b]));
G[b].pb(mp(a,c)); pri(ret);
edge[i]=mp(a,b); }
} }
dfs(0,-1); return 0;
hld(0,0,-1); }
int resolve(string &s){
Aho Corasick int v = 0, r = 0;
for (int i = 0; i < s.size(); i++) {
const int N=100010; //tamanho da trie v = to[v][s[i]];
const int M=26; // tamanho do alfabeto if (fim[v]) r++, v = 0;
int to[N][M], Link[N], fim[N]; }
int idx = 1; return r;
void add_str(string &s){ }
int v = 0;
for (int i = 0; i < s.size(); i++) { Hash Polinomial
if (!to[v][s[i]]) to[v][s[i]] = idx++;
v = to[v][s[i]]; #define MOD 1000000007 //Mod grande
} #define base 33 //Primo um pouco maior que alfabeto
fim[v] = 1; string ss; //String do hash
} vector<ll> pot; //Potencias pre calculadas
void process(){ vector<ll> pre; //Hash de prefixo
queue<int> fila; void calcPot(int n){
fila.push(0); pot.pb(1);
while (!fila.empty()) { for(int i=1;i<n;i++){
int cur = fila.front(); pot.pb(pot[i-1]*base);
fila.pop(); pot[i]%=MOD;
int l = Link[cur]; }
fim[cur] |= fim[l]; }
for (int i = 0; i < M; i++) { void calcPre(int n){ //LEMBRAR DE CHAMAR
if (to[cur][i]) { pre.pb(ss[0]-'0'+1);
if (cur != 0) for(int i=1;i<n;i++){
Link[to[cur][i]] = to[l][i]; pre.pb(pre[i-1]*base+ss[i]-'0'+1);
else pre[i]%=MOD;
Link[to[cur][i]] = 0; }
fila.push(to[cur][i]); }
} ll hash(int i,int j){
else { if(i==0)return pre[j];
to[cur][i] = to[l][i]; ll ret=pre[j]-pre[i-1]*pot[j-i+1];
} ret%=MOD;
} if(ret<0)ret+=MOD;
} return ret;
} }
int centroid=fcentroid(root,root);
Centroid Decomposition O(n*logn) if(p==-1)p=centroid;
ctree[centroid]=p;
#define MAXN 100010 cvis[centroid]=true;
vi G[MAXN]; //cout<<p+1<<"->"<<centroid+1<<endl;
int ctree[MAXN]; for(int i=0;i<G[centroid].size();i++)
int cvis[MAXN]; {
int subt[MAXN]; int va=G[centroid][i];
int nn; if(!cvis[va])
void dfs(int v,int p) decompose(va,centroid);
{ }
subt[v]=1; }
nn++; int main()
for(int i=0;i<G[v].size();i++) {
{ int n;
int va=G[v][i]; sc(n);
if(va!=p && !cvis[va]) for(int i=0;i<n-1;i++)
{ {
dfs(va,v); int a,b;
subt[v]+=subt[va]; sc2(a,b);
} a--,b--;
} G[a].pb(b);
} G[b].pb(a);
int fcentroid(int v,int p) }
{ decompose(0,-1);
for(int i=0;i<G[v].size();i++) return 0;
{ }
int va=G[v][i];
if(va!=p && subt[va]>nn/2 && !cvis[va])return
fcentroid(va,v);
}
return v;
}
void decompose(int root,int p)
{
nn=0;
dfs(root,root);
Geometria 2D TYPE norm(pt a) { return a||a; }
TYPE abs(pt a) { return sqrt(a||a); }
typedef double TYPE; TYPE dist(pt a, pt b) { return abs(a - b); }
const TYPE EPS = 1e-9; TYPE area(pt a, pt b, pt c) { return (a-c)%(b-c); }
int ccw(pt a, pt b, pt c) {return sgn(area(a, b, c)); }
inline int sgn(TYPE a) { return a > EPS ? 1 : (a >= - pt unit(pt a) { return a/abs(a); }
EPS ? 0 : -1); } double arg(pt a) { return atan2(a.y, a.x); }
inline int cmp(TYPE a, TYPE b) { return sgn(a - b); } pt f_polar(TYPE mod, double ang) { return pt(mod *
cos(ang), mod * sin(ang)); }
struct pt { inline int g_mod(int i, int n) { if(i == n) return 0;
TYPE x, y; return i; }
pt(TYPE x = 0, TYPE y = 0) : x(x), y(y) { }
ostream& operator<<(ostream& o, pt p) {
bool operator==(pt p) { return cmp(x, p.x) == 0 && return o << "(" << p.x << "," << p.y << ")";
cmp(y, p.y) == 0; } }
bool operator<(pt p) const { /** funcoes de intercecao **/
return cmp(x, p.x) ? cmp(x, p.x) < 0 : cmp(y, //dentro do retangulo de vertices opostos r0 e r1
p.y) < 0; bool in_rect(pt r0, pt r1, pt p)
} {
bool operator<=(pt p) { return *this < p || *this return sgn(p.x - min(r0.x, r1.x)) >= 0 &&
== p; } sgn(max(r0.x, r1.x) - p.x) >= 0 &&
TYPE operator||(pt p) { return x*p.x + y*p.y; } sgn(p.y - min(r0.y, r1.y)) >= 0 &&
TYPE operator%(pt p) { return x*p.y - y*p.x; } sgn(max(r0.y, r1.y) - p.y) >= 0;
pt operator~() { return pt(x, -y); } }
pt operator+(pt p) { return pt(x + p.x, y + p.y); } //no segmento ab
pt operator-(pt p) { return pt(x - p.x, y - p.y); } bool ps_isects(pt a, pt b, pt p) { return ccw(a,b,p) ==
pt operator*(pt p) { return pt(x*p.x - y*p.y, x*p.y 0 && in_rect(a,b,p); }
+ y*p.x); } //segmentos intersectam
pt operator/(TYPE t) { return pt(x/t, y/t); } bool ss_isects(pt a0,pt a1,pt b0,pt b1)
pt operator/(pt p) { return (*this * ~p)/(p||p); } {
}; if(ccw(a0,a1,b0)*ccw(a0,a1,b1)==-1 and
const pt I = pt(0,1); ccw(b0,b1,a0)*ccw(b0,b1,a1)==-1)return true;
struct circle { return ps_isects(a0,a1,b0) or ps_isects(a0,a1,b1)
pt c; TYPE r; or
circle(pt c, TYPE r) : c(c), r(r) { } ps_isects(b0,b1,a0) or ps_isects(b0,b1,a1);
}; }
//intececao de retas parametrizadas p+vt, q+wt //distancia ponto segmento
pt parametric_isect(pt p, pt v, pt q, pt w) double ps_dist(pt p, pt a, pt b)
{ {
double t = ((q-p)%w)/(v%w); p = p - a; b = b - a;
return p + v*t; double coef = min(max((b||p)/(b||b), TYPE(0)),
} TYPE(1));
return abs(p - b*coef);
//intersecao de segmentos }
pt ss_isect(pt p, pt q, pt r, pt s) /** poligonos **/
{ double p_signedarea(vector<pt> & pol)
pt isect = parametric_isect(p, q-p, r, s-r); {
if(ps_isects(p, q, isect) && ps_isects(r, s, double ret=0;
isect)) return isect; for(int i=0;i<pol.size();i++)
return pt(-INF, -INF); ret+=pol[i]%pol[(i+1)%pol.size()];
} return ret/2;
}
//intersecao de segmento com retangulo vector<pt> hull(vector<pt> pts)
bool sr_isects(pt p0,pt p1,pt r0,pt r1) {
{ if(pts.size()<=1)return pts;
if(in_rect(r0,r1,p0) or in_rect(r0,r1,p1))return vector<pt>ret;
true; sort(pts.begin(),pts.end());
pt r2(r1.x,r0.y); int sz=0;
pt r3(r0.x,r1.y); for(int i=0;i<pts.size();i++)
return ss_isects(p0,p1,r0,r2) or {
ss_isects(p0,p1,r2,r1) or while(sz>=2 && ccw(ret[sz-2],ret[sz-
ss_isects(p0,p1,r1,r3) or ss_isects(p0,p1,r3,r0); 1],pts[i])<=0)
} ret.pop_back(), sz--;
//pontos colineares ret.pb(pts[i]);
bool p_collinear(vector<pt> &v) sz++;
{ }
if(v.size()<3) for(int i=pts.size()-2, t=sz+1;i>=0;i--)
return true; {
for(int i=2;i<v.size();i++) while(sz>=t && ccw(ret[sz-2],ret[sz-
if(ccw(v[0],v[1],v[i])!=0) 1],pts[i])<=0)
return false; ret.pop_back(), sz--;
return true; ret.pb(pts[i]);
} sz++;
} if(px[i]<=pivot)lx.pb(px[i]);
ret.pop_back(); else rx.pb(px[i]);
return ret; for(int i=0;i<py.size();i++)
} if(py[i]<=pivot)ly.pb(py[i]);
vector<pt> cutPolygon(vector<pt>&pol,pt p0,pt p1) else ry.pb(py[i]);
{ pair<pt,pt> r1=closest_p(lx,ly);
vector<pt> ret; pair<pt,pt> r2=closest_p(rx,ry);
for(int i=0;i<pol.size();i++) double
{ delta=min(dist(r1.fi,r1.se),dist(r2.fi,r2.se));
pt q0=pol[i]; if(dist(r1.fi,r1.se)<dist(r2.fi,r2.se))
pt q1=pol[(i+1)%pol.size()]; ret=r1;
if(ccw(p0,p1,q0)>=0) else
ret.pb(q0); ret=r2;
if(ss_isects(q0,q1,p0,p1)) vector<pt> cand;
ret.pb(ss_isect(q0,q1,p0,p1)); for(int i=0;i<py.size();i++)
} {
return ret; if(cmp(abs(py[i].x-pivot.x),delta)<=0)
} cand.pb(py[i]);
//nao trata 2 pontos "iguais" }
pair<pt,pt> closest_p(vector<pt> &px,vector<pt> &py) for(int i=0;i<cand.size();i++)
{ {
pair<pt,pt> ret=mp(pt(-INF,-INF),pt(INF,INF)); for(int j=i+1;j<min((int)cand.size(),i+7);j++)
if(px.size()<=3) {
{ double curr=dist(cand[i],cand[j]);
double best=LINF; if(curr<delta)
for(int i=0;i<px.size();i++) {
for(int j=i+1;j<px.size();j++) delta=curr;
if(dist(px[i],px[j])<best) ret=mp(cand[i],cand[j]);
{ }
ret=mp(px[i],px[j]); }
best=dist(px[i],px[j]); }
} return ret;
return ret; }
}
pt pivot=px[ (px.size()-1)/2];
vector<pt> lx,ly,rx,ry;
for(int i=0;i<px.size();i++)
Baby-step Giant-step Teorema de König (Cobertura de vértices e Max Match )
//Resolve Logaritmo Discreto a^x = b mod m, m primo em
O(sqrt(n)*hash(n))
//Meet In The Middle, decompondo x = i * ceil(sqrt(n))
-j, i,j<=ceil(sqrt(n))
int babyStep(int a,int b,int m)
{
unordered_map<int,int> mapp;
int sq=sqrt(m)+1;
ll asq=1;
for(int i=0; i<sq; i++)
asq=(asq*a)%m;
ll curr=asq;
for(int i=1; i<=sq; i++)
{
if(!mapp.count(curr))
mapp[curr]=i;
curr=(curr*asq)%m;
}
int ret=INF;
curr=b;
for(int j=0; j<=sq; j++)
{ Teorema de Erdős–Gallai (Existência de um Grafo):
if(mapp.count(curr))
ret=min(ret,(int)(mapp[curr]*sq-j));
curr=(curr*a)%m;
}
if(ret<INF) return ret;
return -1;
}
Lei dos cossenos Teorema de Pick (Polígonos simples em pontos inteiros):
(Área, Pontos Internos e Borda)

Teorema de Herão

Burnside’s Lemma(Combinações a menos de rotações g):


Aproximação de Stirling

Fibonacci em log

Período de Pisano (Teoria dos Números):

Para Qualquer inteiro N, a sequência Fibonacci tomada módulo N é


periódica. O tamanho do período é chamado de π(n)(período de Pisano).
Teorema de Euler (para poliedros convexos): Como exemplo, π(3)=8. Veja os primeiros fibonacci módulo 3:

0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0,

You might also like