需要看(有些需要打标*)内容:
线段树*
快速幂*
LCA(tarjan)(树上倍增)*
卡特兰数
概率
快速幂:
int ksm(int a(乘数),int b(次方))
{
int r=1,base=a;
while(b!=0)
{
if(b%2==1)二进制该位为1
r*=base;
base*=base;
b=b/2;
}
return r;
}
LCA(tarjan)(树上倍增)
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,head[10005],t=0,fa[10005],way[10005],root,vis[10055],ff[10005][150];
way表示层数,fa表示祖先,root为树根,vis表示访问与否,ff表示倍增所能跳到的祖先
struct node
{
int from,to,next;
}e[40005];
int build(int a,int b)
{
t++;
e[t].from=a;
e[t].to=b;
e[t].next=head[a];
head[a]=t;
t++;
e[t].from=b;
e[t].to=a;
e[t].next=head[b];
head[b]=t;
}//双向建边
int fi(int u)
{
if(fa[u]!=u)fa[u]=fi(fa[u]);
return fa[u];
}//找父亲
int bu(int root)//建层
{
int bia[10005],tail=1,h=0,qu[30005];
bia[root]=1;
qu[1]=root;
while(h<tail)
{
h++;
for(int i=head[qu[h]];i!=0;i=e[i].next)
{
if(bia[e[i].to]==0)
{
tail++;
qu[tail]=e[i].to;
bia[e[i].to]=1;
way[e[i].to]=way[e[i].from]+1;
fa[e[i].to]=e[i].from;
}
}
}
return 0;
}
int main()
{
cin>>n>>m>>root;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
build(a,b);
}
bu(root);//建层
for(int i=1;i<=n;i++)
{
ff[i][0]=fa[i];
}2的0次方等于1;
for(int i=1;i<=14;i++)
{
for(int j=1;j<=n;j++)
ff[j][i]=ff[ff[j][i-1]][i-1];
}
int a,b;
cin>>a>>b;
if(way[a]>way[b])
swap(a,b);
while(way[b]>way[a])
{
b=fa[b];
}//使两个跳到一个层数上
if(a==b)
{
cout<<a<<endl;
return 0;
}
for(int i=14;i>=0;i--)
{
if(ff[a][i]!=ff[b][i])
{
a=ff[a][i];
b=ff[b][i];
}
}
cout<<fa[a];
}
卡特兰数
令h(0)=1,h(1)=1,catalan数满足递推式:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + … + h(n-1)*h(0) (n>=2)
例题如(出栈序列)