1、倍增法求LCA
#include
using namespace std;
const int maxn = 500600;
int lg[maxn];
struct edge{
int v,nxt;
}e[maxn<<1];
int fa[maxn][22];
int depth[maxn*10];
int head[maxn];
int ecnt;
void init(){
ecnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v){
e[ecnt].v=v;
e[ecnt].nxt=head[u];
head[u]=ecnt++;
}
void dfs(int f,int father){
depth[f]=depth[father]+1;
fa[f][0]=father;
for(int i=1;(1<<i)<=depth[f];i++){
fa[f][i]=fa[fa[f][i-1]][i-1];
}
for(int i=head[f];i+1;i=e[i].nxt){
if(e[i].v!=father){
dfs(e[i].v,f);
}
}
}
int lca(int x,int y){
if(depth[x]<depth[y]){
swap(x,y);
}
while(depth[x]>depth[y]){
x=fa[x][lg[depth[x]-depth[y]]-1];
}
if(x==y) return x;
for(int k=lg[depth[x]];k>=0;k--){
if(fa[x][k]!=fa[y][k]){
x=fa[x][k];
y=fa[y][k];
}
}
return fa[x][0];
}
int main(){
int n,m,s,x,y;
scanf("%d %d %d",&n,&m,&s);
init();
for(int i=1;i<=n-1;i++){
scanf("%d %d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs(s,0);
for(int i=1;i<=n;i++){
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
for(int i=1;i<=m;i++){
scanf("%d %d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}
2、组合数+阶乘逆元打表
void init(){
fact[0]=inv[1]=factinv[0]=inv[0]=fact[1]=factinv[1]=1;
for(int i=2;i<=MAXN;i++){
fact[i]=(fact[i-1]%mod*i%mod)%mod;
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
factinv[i]=factinv[i-1]*inv[i]%mod;
}
}
ll c(ll n,ll m){
return fact[n]*factinv[m]%mod*factinv[n-m]%mod;
}
3、EK算法求网络最大流
#include
using namespace std;
const int maxn = 105000;
const int INF = 0x3f3f3f3f;
struct edge{
int v,w,nxt;
}e[maxn<<1];
int head[maxn];
int cnt=0;
bool vis[maxn];
struct node{
int id,v;
}pre[maxn];
int n,m,s,t,a,b,c;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
}
void addedge(int u,int v,int w){
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
bool bfs(int s,int t){
queue<int> q;
memset(vis,0,sizeof(vis));
memset(pre,0,sizeof(pre));
q.push(s);
pre[s].v=s;
vis[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i+1;i=e[i].nxt){
int v=e[i].v;
if(!vis[v]&&e[i].w){
vis[v]=1;
pre[v].v=u;
pre[v].id=i;
if(v==t) return true;
q.push(v);
}
}
}
return false;
}
int EK(int s,int t){
int ans=0;
int minn;
while(bfs(s,t)){
minn=INF;
for(int i=t;i!=s;i=pre[i].v){
minn=min(minn,e[pre[i].id].w);
}
for(int i=t;i!=s;i=pre[i].v){
e[pre[i].id].w-=minn;
e[pre[i].id^1].w+=minn;
}
ans+=minn;
}
return ans;
}
int main(){
cin>>n>>m;
init();
for(int i=1;i<=m;i++){
cin>>a>>b>>c;
addedge(a,b,c);
addedge(b,a,0);
}
cout<<EK(1,n)<<endl;
return 0;
}
4、dinic求最大流
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 2000001
#define M 8000010
#define inf 1<<26
#define p(a,b) m*(a-1)+b
using namespace std;
inline int read()
{
int x=0,f=1;char ch;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,ss,tt;
int head[N],pos=-1,cur[N];
struct edge{int to,next,c;}e[M];
void addedge(int a,int b,int c)
{pos++;e[pos].to=b,e[pos].next=head[a],e[pos].c=c,head[a]=pos;}
queue<int>Q;bool vis[N];int d[N];
bool bfs()
{
for(int i=ss;i<=tt;i++)vis[i]=0,d[i]=-1;
while(!Q.empty())Q.pop();
d[ss]=0,vis[ss]=1;Q.push(ss);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(e[i].c<=0||vis[v])
continue;
d[v]=d[u]+1;
vis[v]=1;Q.push(v);
}
}return vis[tt];
}
int dfs(int u,int a)
{
if(u==tt||!a)return a;
int flow=0,f;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c)))>0)
{
flow+=f,a-=f;
e[i].c-=f,e[i^1].c+=f;
if(!a)break;
}
}return flow;
}
int dinic()
{
int ret=0;
while(bfs())
{
for(int i=ss;i<=tt;i++)cur[i]=head[i];
ret+=dfs(ss,inf);
}return ret;
}
void init(){memset(head,-1,sizeof(head));}
5、最小费用最大流
#include
using namespace std;
const int maxn = 100050;
const int INF = 0x3f3f3f3f;
int head[maxn];
bool vis[maxn];
int dis[maxn];
int flow[maxn];
int n,m,s,t;
struct edge{
int v,f,c,next;
}e[maxn];
struct node{
int id;
int v;
}pre[maxn];
int cnt;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
}
void addedge(int u,int v,int f,int c){
e[cnt].v=v;
e[cnt].f=f;
e[cnt].c=c;
e[cnt].next=head[u];
head[u]=cnt++;
}
bool spfa()
{
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(flow,INF,sizeof(flow));
queue<int>que;
que.push(s);dis[s]=0;
while(!que.empty())
{
int u=que.front();que.pop();
vis[u]=0;
for(int i=head[u];i+1;i=e[i].next)
{
int v=e[i].v,di=e[i].c,c=e[i].f;
if(c&&dis[v]>dis[u]+di)
{
dis[v]=dis[u]+di;
pre[v].id=i;
pre[v].v=u;
flow[v]=min(c,flow[u]);
if(!vis[v])
{
que.push(v);vis[v]=1;
}
}
}
}
return flow[t]!=flow[s];
}
void MCMF()
{
int mf=0;
int mc=0;
while(spfa())
{
mf+=flow[t];
mc+=flow[t]*dis[t];
for(int u=t;u!=s;u=pre[u].v)
{
int v=pre[u].id;
e[v].f-=flow[t];
e[v^1].f+=flow[t];
}
}
printf("%d %d\n",mf,mc);
}
int main(){
init();
cin>>n>>m>>s>>t;
int u,v,f,c;
for(int i=1;i<=m;i++){
cin>>u>>v>>f>>c;
addedge(u,v,f,c);
addedge(v,u,0,-c);
}
MCMF();
return 0;
}
6、高精度加法
#include
#include
#include
using namespace std;
const int L=11000;
string add(string a,string b)
{
string ans;
int na[L]={0},nb[L]={0};
int la=a.size(),lb=b.size();
for(int i=0;i<la;i++) na[la-1-i]=a[i]-'0';
for(int i=0;i<lb;i++) nb[lb-1-i]=b[i]-'0';
int lmax=la>lb?la:lb;
for(int i=0;i<lmax;i++) na[i]+=nb[i],na[i+1]+=na[i]/10,na[i]%=10;
if(na[lmax]) lmax++;
for(int i=lmax-1;i>=0;i--) ans+=na[i]+'0';
return ans;
}
int main()
{
string a,b;
while(cin>>a>>b) cout<<add(a,b)<<endl;
return 0;
}
7、高精度减法
#include
#include
#include
using namespace std;
const int L=11000;
string sub(string a,string b)
{
string ans;
int na[L]={0},nb[L]={0};
int la=a.size(),lb=b.size();
for(int i=0;i<la;i++) na[la-1-i]=a[i]-'0';
for(int i=0;i<lb;i++) nb[lb-1-i]=b[i]-'0';
int lmax=la>lb?la:lb;
for(int i=0;i<lmax;i++)
{
na[i]-=nb[i];
if(na[i]<0) na[i]+=10,na[i+1]--;
}
while(!na[--lmax]&&lmax>0) ;lmax++;
for(int i=lmax-1;i>=0;i--) ans+=na[i]+'0';
return ans;
}
int main()
{
string a,b;
while(cin>>a>>b) {
if(a.length()<b.length()){
cout<<"-"<<sub(b,a)<<endl;
}
else if(a.length()==b.length()){
if(a<b) cout<<"-"<<sub(b,a)<<endl;
else cout<<sub(a,b)<<endl;
}
else cout<<sub(a,b)<<endl;
}
return 0;
}
8、高精度乘法
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define L(x) (1 << (x))
const double PI = acos(-1.0);
const int Maxn = 133015;
double ax[Maxn], ay[Maxn], bx[Maxn], by[Maxn];
char sa[Maxn/2],sb[Maxn/2];
int sum[Maxn];
int x1[Maxn],x2[Maxn];
int revv(int x, int bits)
{
int ret = 0;
for (int i = 0; i < bits; i++)
{
ret <<= 1;
ret |= x & 1;
x >>= 1;
}
return ret;
}
void fft(double * a, double * b, int n, bool rev)
{
int bits = 0;
while (1 << bits < n) ++bits;
for (int i = 0; i < n; i++)
{
int j = revv(i, bits);
if (i < j)
swap(a[i], a[j]), swap(b[i], b[j]);
}
for (int len = 2; len <= n; len <<= 1)
{
int half = len >> 1;
double wmx = cos(2 * PI / len), wmy = sin(2 * PI / len);
if (rev) wmy = -wmy;
for (int i = 0; i < n; i += len)
{
double wx = 1, wy = 0;
for (int j = 0; j < half; j++)
{
double cx = a[i + j], cy = b[i + j];
double dx = a[i + j + half], dy = b[i + j + half];
double ex = dx * wx - dy * wy, ey = dx * wy + dy * wx;
a[i + j] = cx + ex, b[i + j] = cy + ey;
a[i + j + half] = cx - ex, b[i + j + half] = cy - ey;
double wnx = wx * wmx - wy * wmy, wny = wx * wmy + wy * wmx;
wx = wnx, wy = wny;
}
}
}
if (rev)
{
for (int i = 0; i < n; i++)
a[i] /= n, b[i] /= n;
}
}
int solve(int a[],int na,int b[],int nb,int ans[])
{
int len = max(na, nb), ln;
for(ln=0; L(ln)<len; ++ln);
len=L(++ln);
for (int i = 0; i < len ; ++i)
{
if (i >= na) ax[i] = 0, ay[i] =0;
else ax[i] = a[i], ay[i] = 0;
}
fft(ax, ay, len, 0);
for (int i = 0; i < len; ++i)
{
if (i >= nb) bx[i] = 0, by[i] = 0;
else bx[i] = b[i], by[i] = 0;
}
fft(bx, by, len, 0);
for (int i = 0; i < len; ++i)
{
double cx = ax[i] * bx[i] - ay[i] * by[i];
double cy = ax[i] * by[i] + ay[i] * bx[i];
ax[i] = cx, ay[i] = cy;
}
fft(ax, ay, len, 1);
for (int i = 0; i < len; ++i)
ans[i] = (int)(ax[i] + 0.5);
return len;
}
string mul(string sa,string sb)
{
int l1,l2,l;
int i;
string ans;
memset(sum, 0, sizeof(sum));
l1 = sa.size();
l2 = sb.size();
for(i = 0; i < l1; i++)
x1[i] = sa[l1 - i - 1]-'0';
for(i = 0; i < l2; i++)
x2[i] = sb[l2-i-1]-'0';
l = solve(x1, l1, x2, l2, sum);
for(i = 0; i<l || sum[i] >= 10; i++)
{
sum[i + 1] += sum[i] / 10;
sum[i] %= 10;
}
l = i;
while(sum[l] <= 0 && l>0) l--;
for(i = l; i >= 0; i--) ans+=sum[i] + '0';
return ans;
}
int main()
{
cin.sync_with_stdio(false);
string a,b;
while(cin>>a>>b) cout<<mul(a,b)<<endl;
return 0;
}
9、高精度除法
#include
#include
#include
using namespace std;
const int L=11000;
int sub(int *a,int *b,int La,int Lb)
{
if(La<Lb) return -1;
if(La==Lb)
{
for(int i=La-1;i>=0;i--)
if(a[i]>b[i]) break;
else if(a[i]<b[i]) return -1;
}
for(int i=0;i<La;i++)
{
a[i]-=b[i];
if(a[i]<0) a[i]+=10,a[i+1]--;
}
for(int i=La-1;i>=0;i--)
if(a[i]) return i+1;
return 0;
}
string div(string n1,string n2,int nn)
{
string s,v;
int a[L],b[L],r[L],La=n1.size(),Lb=n2.size(),i,tp=La;
fill(a,a+L,0);fill(b,b+L,0);fill(r,r+L,0);
for(i=La-1;i>=0;i--) a[La-1-i]=n1[i]-'0';
for(i=Lb-1;i>=0;i--) b[Lb-1-i]=n2[i]-'0';
if(La<Lb || (La==Lb && n1<n2)) {
10、整除分块
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
11、分层图最短路
#include
using namespace std;
const int maxn = 1500050;
const int INF = 0x3f3f3f3f;
int n,m,k;
int vis[maxn];
int head[maxn];
int st,ed;
int cnt;
int dis[maxn];
struct EDGE{
int from;
int to;
int val;
int next;
}e[maxn<<1];
struct node{
int id;
int d;
};
bool operator< (node a,node b){
return a.d>b.d;
}
void init(){
cnt=1;
memset(head,-1,sizeof(head));
}
void addedge(int a,int b,int c){
e[cnt].from=a;
e[cnt].to=b;
e[cnt].val=c;
e[cnt].next=head[a];
head[a]=cnt++;
}
void dij(int st,int ed){
memset(dis,0x3f,sizeof(dis));
priority_queue<node> q;
node nt;
nt.id=st,nt.d=0;
dis[st]=0;
q.push(nt);
while(!q.empty()){
node rt=q.top();
q.pop();
if(vis[rt.id]) continue;
vis[rt.id]=1;
for(int i=head[rt.id];i!=-1;i=e[i].next){
if(dis[e[i].to]>dis[rt.id]+e[i].val){
dis[e[i].to]=dis[rt.id]+e[i].val;
nt.id=e[i].to;
nt.d=dis[e[i].to];
q.push(nt);
}
}
}
int ans=INF;
for(int i=0;i<=k;i++){
ans=min(ans,dis[i*n+ed]);
}
printf("%d\n",ans);
}
int main(){
init();
scanf("%d %d %d %d %d",&n,&m,&k,&st,&ed);
int a,b,c;
for(int i=1;i<=m;i++){
scanf("%d %d %d",&a,&b,&c);
for(int j=0;j<=k;j++){
addedge(a+j*n,b+j*n,c);
addedge(b+j*n,a+j*n,c);
if(j!=k){
addedge(a+j*n,b+(j+1)*n,0);
addedge(b+j*n,a+(j+1)*n,0);
}
}
}
dij(st,ed);
return 0;
}
12、卡特兰数打表
#include
#include
using namespace std;
int ans[200][3000];
void ktl()
{
ans[1][0]=1;
ans[2][0]=1;
ans[1][1]=1;
ans[2][1]=2;
int len=1;
int carry;
for(int i=3;i<=102;i++)
{
carry=0;
for(int j=1;j<=len;j++)
{
int t=ans[i-1][j]*(4*i-2)+carry;
carry=t/10;
ans[i][j]=t%10;
}
while(carry)
{
ans[i][++len]=carry%10;
carry/=10;
}
for(int j=len;j>=1;j--)
{
int t=ans[i][j]+carry*10;
ans[i][j]=t/(i+1);
carry=t%(i+1);
}
while(!ans[i][len])
{
len--;
}
ans[i][0]=len;
}
}
int main()
{
ktl();
int n;
while(cin>>n)
{
for(int i=ans[n][0];i>0;i--)
{
cout<<ans[n][i];
}
cout<<endl;
}
return 0;
}
13、矩阵快速幂
#include
using namespace std;
typedef long long ll;
const ll maxn = 10;
const ll mod = 1000000009;
struct mart{
ll m[100][100];
}unit;
mart mult(mart a,mart b){
mart ans;
int x;
for(ll i=0;i<4;i++){
for(ll j=0;j<4;j++){
x=0;
for(ll k=0;k<4;k++){
x=(x%mod+(a.m[i][k]%mod*b.m[k][j]%mod)%mod)%mod;
}
ans.m[i][j]=x%mod;
}
}
return ans;
}
void init(){
for(ll i=0;i<4;i++){
unit.m[i][i]=1;
}
}
mart qpow(mart a,ll b){
init();
mart ans=unit;
while(b){
if(b&1) ans=mult(ans,a);
a=mult(a,a);
b>>=1;
}
return ans;
}
ll solve(ll n){
mart a,b;
a.m[0][0]=1;
a.m[0][1]=1;
a.m[1][0]=1;
a.m[1][1]=0;
b.m[0][0]=1;
b.m[1][0]=0;
mart c=mult(qpow(a,n-2),b);
return c.m[0][0]%mod;
}
int main(){
ll n;
cin>>n;
if(n==0) puts("0");
else
cout<<solve(n+1)<<endl;
return 0;
}
14、最短路(dijkstra:链式前向星)
#include
using namespace std;
typedef long long ll;
const int INF = 2147483647;
const int maxn = 1005000;
struct node{
ll d;
int u;
};
bool operator<(node a,node b){
return a.d>b.d;
}
struct edge{
int v,w,nxt;
}e[maxn<<1];
int head[maxn];
bool vis[maxn];
ll dis[maxn];
int n,m,cnt;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
}
void addedge(int u,int v,int w){
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void dij(int s){
priority_queue<node> q;
for(int i=1;i<=n;i++){
dis[i]=INF;
}
dis[s]=0;
memset(vis,0,sizeof(vis));
node tn;
tn.d=0;
tn.u=s;
q.push(tn);
while(!q.empty()){
node rt=q.top();q.pop();
int u=rt.u;
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i+1;i=e[i].nxt){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
tn.d=dis[v];
tn.u=v;
q.push(tn);
}
}
}
}
int main(){
ios::sync_with_stdio(0);
int s;
init();
cin>>n>>m>>s;
int a,b,c;
for(int i=1;i<=m;i++){
cin>>a>>b>>c;
addedge(a,b,c);
}
dij(s);
for(int i=1;i<=n;i++){
if(i!=1) cout<<" "<<dis[i];
else cout<<dis[i];
}
cout<<endl;
return 0;
}